Skip to content

Instantly share code, notes, and snippets.

@urielieli
Created July 11, 2017 18:57
Show Gist options
  • Save urielieli/5842ba6f23cee2b829224d4b1b074375 to your computer and use it in GitHub Desktop.
Save urielieli/5842ba6f23cee2b829224d4b1b074375 to your computer and use it in GitHub Desktop.
import string
from math import inf
class base:
"""manages metadata and conversions methods for unary and positional numeric systems"""
def __init__ (self, base = 10,
charset = string.digits + string.ascii_uppercase + string.ascii_lowercase,
radix_point = '.',
precision = 30):
"""
@ parameters
base : int, optional
used for conversions
limitations:
encoding : ∀ base, base ϵ 𝓝, base ϵ [1, ∞)
decoding : ∀ base, base ϵ 𝒞, base ϵ [-∞, 0), (0, ∞]
charset : string, optional
used to determine the value of every character
radix_point : string, optional
used to show and determine the radix point form
precision : int, optional
used to determine precision in conversion
"""
self.base = base
self.charset = charset
self.radix_point = radix_point
self.precision = precision
def encode (self, number):
"""
encodes a number in the base
@ parameters
number : numerical data-type
decimal number to be encoded in the base
the data-type must support:
__abs__, __floordiv__, __mod__,
__mul__, __gt__, __lt__, __int__
@ returns
string
the decimal number encoded in the base
"""
sign, integer, fraction = '-' * (number < 0), int(abs(number) // 1), abs(number) % 1
if self.base == 1:
return sign + ('1' * integer or self.charset[0]) + \
(self.radix_point + \
self.radix_point.join(
map('1'.__mul__,
map(int, str(fraction).rpartition(self.radix_point)[2])
)
)
) if fraction else ''
if isinstance(self.base, complex):
real_integer, real_fraction = base((self.base ** 2).real).encode(number.real).split(self.radix_point)
imag_integer, imag_fraction = base((self.base ** 2).real).encode(number.imag).split(self.radix_point)
integer_part = ''.join(zip(imag_fraction, real_fraction))
fraction_part = ''.join(zip(real_fraction, imag_fraction))
return (integer_part or self.charset[0]) + (self.radix_point + fractional_part) if fractional_part else ''
integer_part = ''
while integer > 0:
integer_part = (self.charset[integer % self.base] if integer % self.base < len(self.charset) else '?') + integer_part
integer //= self.base
fractional_part = ''
while fraction % 1 > 0 and len(fractional_part) < self.precision:
fraction = fraction % 1 * self.base
fractional_part = fractional_part + (self.charset[int(fraction // 1)] if int(fraction // 1) < len(self.charset) else '?')
return sign + (integer_part or self.charset[0]) + (fractional_part and (self.radix_point + fractional_part) or '')
def decode (self, number):
"""
decodes a number in the base back to decimal
@ parameters
number : string
representing a number in the base to be converted to decimal
@ returns
float
the number converted to decimal
"""
sign = 2 * (len(number) == 0 or number[0] != '-') - 1
integer_part, _, fractional_part = number.partition(self.radix_point)
integer_part = integer_part.lstrip('-')
if self.base == 1:
fraction, exponent = 0, 0.1
for section in fractional_part.split(self.radix_point):
fraction += len(section) * exponent
exponent /= 10
return sign * (len(integer_part) + fraction)
integer, exponent = 0, 1
for digit in integer_part[::-1]:
integer += self.charset.index(digit) * exponent
exponent *= self.base
fraction, exponent = 0, 1 / self.base
for digit in fractional_part:
fraction += self.charset.index(digit) * exponent
exponent /= self.base
return sign * (integer + fraction)
def convert (self, base):
"""
provides a converter from the current base to the given base
@ parameters
base : base
the base to which the converter will convert
@ returns
lambda (numerical data-type)
a function converting a number from the base to the other base
"""
return lambda number: base.encode(self.decode(number))
def __contains__ (self, number):
"""
provides indication whether the given number is valid in the
context of the current base
@ parameters
number : string
representing a number in the base
@ returns
bool
thruthy value if number is valid, otherwise falsy value
"""
if self.base == 1:
return all(digit in '1.' for digit in number)
if self.base == inf:
return True
return all(digit in self.charset[:self.base] or digit == '-' for digit in number)
def __eq__ (self, base):
"""
provides indication whether the base shares the same properties
with another base
@ parameters
base : base
the base tested for equality
@ returns
bool
thruthy value if bases shares the same properties, otherwise falsy value
"""
return (self.base, self.charset, self.precision) == (base.base, base.charset, base.precision)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment