Created
February 20, 2018 15:11
-
-
Save avdotion/cccf91291ded4a53c799072a6e79de71 to your computer and use it in GitHub Desktop.
Перевод из одной системы счисления в другую
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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