Skip to content

Instantly share code, notes, and snippets.

@avdotion
Created February 20, 2018 15:11
Show Gist options
  • Save avdotion/cccf91291ded4a53c799072a6e79de71 to your computer and use it in GitHub Desktop.
Save avdotion/cccf91291ded4a53c799072a6e79de71 to your computer and use it in GitHub Desktop.
Перевод из одной системы счисления в другую
class Number:
def __init__(self, value, base):
'''Конструктор класса'''
# Проверка на тип
# Класс основан на работе со списком значений (цифр числа)
# На этом шаге ~любой тип преобразуется в список строк
if isinstance(value, type(1)):
self.value = list(str(value))
elif isinstance(value, type([])):
self.value = value
elif isinstance(value, type('')):
self.value = list(value)
else:
# Исключение, которое заставляет пользователя отправлять в класс
# только допустимые типы в качестве value
raise TypeError('type of number must be int, list or str')
# Пустота - ноль
if len(self.value) == 0:
self.value = ['0']
try:
# Преобразование основания СС в int
self.base = int(base)
except ValueError:
raise ValueError('base must be int or special value')
if not 2 <= self.base <= 36:
raise ValueError('base must be in [2...36]')
# Проверка, действительно ли число умещается в указанное основание СС
for symbol in self.value:
if self._get_code(symbol) >= self._get_code(self.base):
raise ValueError('value must be typed in selected base')
def convert(self, foo_base):
'''Функция перевода числа в новую CC'''
# Для того, чтобы перевести число из СС с основанием base
# в число с основанием foo_base, следует сначала перевести его из
# base в 10, а затем из 10 в foo_base
# Функция convert(foo_base) возвращает новое значение, не меняя его
# Реальное значение числа сохраним во временной переменной temp_value,
# чтобы без опаски его изменять
temp_value = self.value
# Как и в функции конструктора, следует преобразовать основание СС в int
try:
foo_base = int(foo_base)
except ValueError:
raise ValueError('base must be int or special value')
# Заранее ограничиваем нашу программу тем, что основание СС может быть
# в промежутке [2, 36]
if not 2 <= foo_base <= 36:
raise ValueError('base must be in [2...36]')
# Если число изначально не в десятичной СС,
# то переводим его известным алгоритмом
if self.base != 10:
result = 0
for i in range(len(self.value)):
# Внимание: нумерация начинается с нуля, а ход по разрядам
# идет справа налево
result += self.base ** i * self._get_code(self.value[-i - 1])
temp_value = result
else:
# Теперь temp_value - это int
temp_value = int(''.join(temp_value))
# Если мы хотели перевести в десятичную, то самое время остановиться
if foo_base == 10:
return Number(temp_value, foo_base)
# Формируем новый список, в котором будут храниться цифры нового числа
result = list()
while temp_value:
# Используем известный алгоритм
result += self._get_symbol(temp_value % foo_base)
temp_value //= foo_base
# Важно вернуть не список, а именно объект класса
return Number(result[::-1], foo_base)
def _get_code(self, symbol):
'''Функция, которая возвращает код символа из таблицы Unicode'''
# Функция не используется за пределами класса, на это указывает префикс '_'
symbol = str(symbol)
if '0' <= symbol <= '9':
return int(symbol)
else:
symbol = symbol.upper()
return ord(symbol) - ord('A') + 10
def _get_symbol(self, code):
'''Функция, которая возвращает символ из таблицы Unicode, зная его код'''
if 0 <= code <= 9:
return str(code)
elif ord("A") <= code + ord('A') - 10 <= ord("Z"):
return chr(code + ord('A') - 10)
else:
raise Exception('undefined exhibition')
def __str__(self):
'''Служебная функция для вывода числа на экран'''
return "".join(self.value)
def __add__(self, other):
'''Функция сложения двух чисел'''
# Проверка на эквивалентность оснований двух СС
if self.base != other.base:
raise ValueError('base of two values must be equal')
else:
# Питон отлично складывает числа в десятичной СС
a = self.convert(10)
b = other.convert(10)
c = Number(int(''.join(a.value)) + int(''.join(b.value)), 10)
return c.convert(self.base)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment