Как работать с разными системами счисления в Python

Раздел: Основы Python -> Перевод систем счисления

Основные методы перевода между системами счисления в Python

Наиболее эффективный способ перевода чисел между системами счисления в Python – использование встроенных функций int(), bin(), oct(), hex() и форматирования строк. Этот подход покрывает все распространённые случаи (двоичная, восьмеричная, десятичная, шестнадцатеричная системы) и выполняется нативно, без написания дополнительного кода.

Функция int('строка', основание) принимает строку, представляющую число в системе с основанием от 2 до 36, и возвращает десятичное целое. Например:

int('1010', 2)   # 10
int('12', 8)     # 10
int('A', 16)     # 10

Python восьмеричная система (восьмеричная система счисления в python)

Для обратного преобразования используются bin(), oct(), hex(), которые возвращают строку с префиксом 0b, 0o или 0x соответственно:

bin(10)    # '0b1010'
oct(10)    # '0o12'
hex(10)    # '0xa'

перевод в другие системы счисления python (перевод в другую систему счисления в python)

Чтобы получить строку без префикса, применяют format() или f-строки:

format(10, 'b')   # '1010'
format(10, 'o')   # '12'
format(10, 'x')   # 'a'

f'{10:b}'          # '1010'
f'{10:o}'          # '12'
f'{10:x}'          # 'a'

16 система счисления python (перевод в шестнадцатеричную систему в python)

Типичные ошибки и их решения:

  • ValueError – если строка содержит недопустимые для данного основания символы. Например, int('12', 2) вызовет ошибку, так как '2' не является двоичной цифрой. Решение: предварительно проверять строку регулярным выражением или обрабатывать исключение.
  • Неверный регистрint('a', 16) корректно, int('A', 16) тоже, но int('A', 10) вызовет ошибку. Рекомендуется использовать единый регистр (строчные) после приведения str.lower().
  • Основание вне диапазона 2–36int('10', 1) или int('10', 37) приводят к ValueError. Для нестандартных оснований (больше 36) нужны собственные алгоритмы.

Когда использовать: если требуется быстрый перевод между системами с основанием 2, 8, 10, 16 или любым другим от 2 до 36, и не нужна особая гибкость (например, собственный алфавит).

Как преобразовать десятичное число в систему с основанием больше 16 или с нестандартным алфавитом?

Встроенные функции ограничены основанием 36. Для произвольного основания (например, 62) необходимо реализовать собственный алгоритм. Классический метод – деление числа на основание с сохранением остатков, которые затем заменяются на символы из заданного алфавита.

def to_base(n, base, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    if n == 0:
        return alphabet[0]
    result = []
    while n > 0:
        result.append(alphabet[n % base])
        n //= base
    return ''.join(reversed(result))

# Примеры
to_base(255, 16)   # 'FF'
to_base(255, 8)    # '377'
to_base(255, 2)    # '11111111'
to_base(1234567890, 62)  # '1LY7VK'

Python перевод в двоичную систему (перевод числа в двоичную систему в python)

Пояснение: функция повторно делит число на основание, берёт остаток от деления и преобразует его в символ по индексу из алфавита. Полученные символы собираются в обратном порядке, так как первый остаток соответствует младшему разряду.

Проблемы и решения:

  • Если алфавит короче основания, возникнет ошибка IndexError. Решение: заранее проверять длину алфавита (len(alphabet) >= base).
  • Отрицательные числа – функция не обрабатывает знак. Решение: добавить проверку if n < 0: return '-' + to_base(-n, base, alphabet).
  • Дробные числа – требуется отдельный алгоритм для дробной части (умножение на основание).

Когда использовать: для перевода в системы с основанием свыше 36, для кастомного алфавита (например, base64), для учебных целей или при необходимости точного контроля над процессом.

Как получить десятичное число из строки, если основание больше 36 или алфавит нестандартный?

Обратное преобразование – из произвольной системы в десятичную – выполняется путём обхода строки и накопления результата по формуле Горнера или суммированием произведений.

def from_base(s, base, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    char_to_val = {c: i for i, c in enumerate(alphabet)}
    result = 0
    for char in s.upper():
        result = result * base + char_to_val[char]
    return result

# Примеры
from_base('FF', 16)        # 255
from_base('11111111', 2)   # 255
from_base('1LY7VK', 62)    # 1234567890

перевод в десятичную систему счисления python (перевод числа в десятичную систему счисления в python)

Пояснение: создаётся словарь соответствия символов их числовым значениям. Для каждого символа строки значение добавляется к результату, предварительно умноженному на основание. Метод Горнера позволяет обойтись без возведения в степень, что эффективнее.

Типичные ошибки:

  • Символ отсутствует в алфавите – KeyError. Решение: предварительно проверять if char not in char_to_val: raise ValueError(...).
  • Разный регистр – функция .upper() приводит строку к верхнему регистру, что предполагает алфавит только из заглавных букв. Если алфавит содержит строчные, нужно заменить на .lower() или не изменять регистр.
  • Основание слишком большое – при большом основании и длинной строке результат может превысить возможности целых чисел Python (но Python поддерживает произвольно большие целые, поэтому это не проблема).

Когда использовать: для разбора строк, полученных из внешних источников, когда стандартное int() не подходит из-за нестандартного алфавита или основания больше 36.

Как перевести дробное десятичное число в другую систему счисления (двоичную, восьмеричную и т.д.)?

Перевод дробной части отличается от целой: дробь многократно умножается на основание, целая часть результата становится очередной цифрой, а дробная часть снова умножается. Процесс продолжается до достижения нужной точности или обнуления дробной части.

def frac_to_base(frac, base, precision=10):
    result = []
    for _ in range(precision):
        frac *= base
        digit = int(frac)
        result.append(str(digit))
        frac -= digit
        if frac == 0:
            break
    return '.' + ''.join(result)

# Пример: 0.625 в двоичной
frac_to_base(0.625, 2)   # '.101'

# 0.1 в двоичной (бесконечная дробь)
frac_to_base(0.1, 2, precision=8)  # '.00011001'

перевод в троичную систему python (перевод числа в троичную систему в python)

Пояснение: функция принимает дробную часть (число от 0 до 1), основание и желаемую точность (количество знаков после запятой). На каждой итерации дробь умножается на основание, целая часть записывается, а от числа остаётся только дробная часть. Процесс останавливается, если дробь стала нулевой, или после достижения заданной точности.

Проблемы:

  • Некоторые дроби не представимы точно в системах с основанием, отличным от их собственного (например, 0.1 в двоичной – периодическая дробь). Решение: ограничить точность или использовать символьные вычисления (библиотека fractions).
  • Ошибки округления из-за представления чисел с плавающей точкой в Python. Решение: использовать Decimal из модуля decimal для точного представления.

Когда использовать: при работе с дробными числами, например, в цифровой обработке сигналов, криптографии или визуализации данных, где требуется точное представление дробной части в другой системе.

Как использовать f-строки и format() для вывода в нескольких системах счисления одновременно?

Для вывода числа сразу в нескольких системах удобно использовать f-строки с разными спецификаторами. Это часто применяется при отладке или логировании.

n = 42
print(f'Десятичное: {n}')
print(f'Двоичное: {n:b}')
print(f'Восьмеричное: {n:o}')
print(f'Шестнадцатеричное: {n:x}')
# Результат:
# Десятичное: 42
# Двоичное: 101010
# Восьмеричное: 52
# Шестнадцатеричное: 2a

Пояснение: спецификаторы :b, :o, :x работают только для целых чисел и не поддерживают произвольные основания. Для вывода с префиксом используют :#b, :#o, :#x (например, f'{42:#b}''0b101010').

Ошибки:

  • Попытка использовать :b для дробного числа – ValueError. Спецификаторы бинарного/восьмеричного/шестнадцатеричного формата применимы только к целым числам.
  • Если нужен вывод с фиксированной шириной поля, можно указать выравнивание, например f'{n:08b}' – дополнит нулями до 8 бит.

Когда использовать: для быстрого форматирования вывода, в скриптах отладки, при генерации отчётов, где нужно компактно отобразить число в нескольких системах.

Расширенные и нестандартные примеры перевода систем счисления

Прямой перевод из одной произвольной системы в другую (без промежуточного десятичного)

Хотя обычно перевод выполняется через десятичное число, можно реализовать прямой алгоритм, используя операции в исходной системе. Однако на практике проще и быстрее сначала перевести в десятичную, а затем в целевую систему. Ниже представлена универсальная функция convert_base, объединяющая оба шага.

Пример
def convert_base(num_str, from_base, to_base,
                 alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    """Перевод числа из системы from_base в систему to_base."""
    # Шаг 1: from_base -> десятичное
    char_to_val = {c: i for i, c in enumerate(alphabet)}
    decimal = 0
    for char in num_str.upper():
        if char not in char_to_val:
            raise ValueError(f"Недопустимый символ '{char}' для основания {from_base}")
        decimal = decimal * from_base + char_to_val[char]

    # Шаг 2: десятичное -> to_base
    if decimal == 0:
        return alphabet[0]
    result = []
    while decimal > 0:
        result.append(alphabet[decimal % to_base])
        decimal //= to_base
    return ''.join(reversed(result))

# Примеры
test_cases = [
    ('1010', 2, 10),   # 10
    ('FF', 16, 2),     # 11111111
    ('123', 4, 16),    # 1B (123_4 = 27_10 = 1B_16)
]
for s, fb, tb in test_cases:
    print(f"{s} из {fb}-ной в {tb}-ную -> {convert_base(s, fb, tb)}")
1010 из 2-ной в 10-ную -> 10
FF из 16-ной в 2-ную -> 11111111
123 из 4-ной в 16-ную -> 1B

Пояснение: функция последовательно выполняет два преобразования, используя общий алфавит. Обратите внимание, что алфавит должен содержать символы для обеих систем. Если основание превышает длину алфавита, потребуется его расширение.

Проблема: при переводе из системы с основанием больше 36 стандартный алфавит не покрывает все возможные цифры. Решение: задавать собственный алфавит, например, включая строчные буквы или дополнительные символы (как в base64).

Рекурсивный перевод в двоичную систему

Классический рекурсивный алгоритм перевода целого числа в двоичную систему: делить число на 2, рекурсивно обрабатывать частное, а остаток добавлять в конец строки.

Пример
def to_binary_recursive(n):
    if n == 0:
        return '0'
    if n == 1:
        return '1'
    return to_binary_recursive(n // 2) + str(n % 2)

# Примеры
for num in [0, 1, 7, 10, 255]:
    print(f"{num} -> {to_binary_recursive(num)}")
0 -> 0
1 -> 1
7 -> 111
10 -> 1010
255 -> 11111111

Пояснение: рекурсия заканчивается, когда число становится 0 или 1. На каждом шаге остаток от деления на 2 (0 или 1) дописывается после рекурсивного вызова, что даёт правильный порядок битов (от старшего к младшему).

Проблема: для очень больших чисел глубина рекурсии может превысить лимит (sys.getrecursionlimit()). Решение: использовать итеративный подход или увеличить лимит, но итеративный способ обычно предпочтительнее.

Перевод с использованием нестандартного алфавита (Base64)

Base64 часто используется в кодировании данных. Его алфавит состоит из 64 символов: A–Z, a–z, 0–9, +, /. Покажем, как перевести число в base64 и обратно, используя собственный алфавит.

Пример
BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

def to_base64(n):
    return to_base(n, 64, BASE64_ALPHABET)

def from_base64(s):
    return from_base(s, 64, BASE64_ALPHABET)

# Пример
num = 12345678901234567890
b64 = to_base64(num)
back = from_base64(b64)
print(f"{num}")
print(f"Base64: {b64}")
print(f"Обратно: {back}")
12345678901234567890
Base64: 9mYSmv0HEu
Обратно: 12345678901234567890

Пояснение: функции to_base и from_base из предыдущих разделов принимают произвольный алфавит. Здесь алфавит base64 используется для представления больших чисел компактно. Отметим, что стандартное кодирование base64 в Python (модуль base64) работает с байтами, а не с числами.

Важно: символы '+' и '/' в URL могут быть проблемными. Существует вариант Base64URL (с заменой '+' на '-' и '/' на '_'). При реализации учитывайте контекст использования.

Обработка больших чисел и проверка корректности входных данных

При работе с вводом пользователя необходимо проверять, что строка действительно представляет число в заданной системе. Пример функции с валидацией.

Пример
import re

def safe_from_base(s, base, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    """Безопасное преобразование строки в десятичное число."""
    # Убираем лишние пробелы и приводим к верхнему регистру
    s = s.strip().upper()
    # Строим регулярное выражение для проверки
    valid_chars = alphabet[:base]
    pattern = f'^[{valid_chars}]+$'
    if not re.match(pattern, s):
        raise ValueError(f"Строка '{s}' содержит недопустимые символы для основания {base}")
    return from_base(s, base, alphabet)

# Тесты
try:
    print(safe_from_base('1A', 16))  # 26
    print(safe_from_base('1G', 16))  # ошибка
except ValueError as e:
    print(f"Ошибка: {e}")
26
Ошибка: Строка '1G' содержит недопустимые символы для основания 16

Пояснение: функция сначала проверяет строку регулярным выражением, которое допускает только символы, входящие в первые base символов алфавита. Затем вызывает уже знакомую from_base.

Проблема: для основания >36 регулярное выражение может стать громоздким, если алфавит содержит спецсимволы. В таких случаях проще проверять каждый символ по словарю, как в from_base.

Работа с отрицательными числами

При переводе отрицательных чисел в другую систему счисления необходимо сохранить знак. Ниже приведён пример, который добавляет знак минус перед результатом.

Пример
def signed_to_base(n, base, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
    if n < 0:
        return '-' + to_base(-n, base, alphabet)
    return to_base(n, base, alphabet)

# Примеры
print(signed_to_base(-255, 16))  # -FF
print(signed_to_base(-42, 2))    # -101010
-FF
-101010

Пояснение: функция проверяет знак числа. Для отрицательных чисел рекурсивно вызывает себя для модуля числа и добавляет префикс '-'. Аналогично для обратного преобразования можно предусмотреть распознавание знака в строке.

Примечание: в некоторых контекстах (например, в компьютерных науках) отрицательные числа представляются в дополнительном коде. Данный подход не реализует такое представление – он просто сохраняет знак.

Перевод в другую систему счисления в Python - comments

En
перевод в другие системы счисления python (python)