Преобразование числовых данных: от строки к integer и обратно
Основные способы преобразования чисел с указанием системы счисления
Для преобразования строки, представляющей число в некоторой системе счисления, в целое число используется встроенная функция int() с параметром base. Например, int('1010', 2) возвращает 10. Для обратного преобразования (числа в строку) применяются строковые методы форматирования: f-строки со спецификаторами b, o, x, d, а также встроенные функции bin(), oct(), hex().
# Преобразование строки в число
value = int('ff', 16)
print(value) # 255
# Преобразование числа в строку в разных системах
num = 255
print(f'{num:b}') # 11111111
print(f'{num:o}') # 377
print(f'{num:x}') # ff
print(f'{num:d}') # 255
Python int система счисления (преобразование чисел с указанием системы счисления в python)
255 11111111 377 ff 255
Если необходимо получить строку с префиксом (0b, 0o, 0x), используются функции bin(), oct(), hex().
print(bin(255)) # 0b11111111
print(oct(255)) # 0o377
print(hex(255)) # 0xff
0b11111111 0o377 0xff
Для удаления префикса применяется срез [2:].
Как преобразовать строку с произвольным основанием от 2 до 36?
Функция int() поддерживает основания от 2 до 36 включительно. Символы должны быть цифрами 0-9 и латинскими буквами a-z (A-Z). Регистр не важен.
# Основание 36
s = 'z'
print(int(s, 36)) # 35
# Основание 5
print(int('432', 5)) # 117 (4*25 + 3*5 + 2 = 117)
35 117
Как выполнить преобразование из одной системы счисления в другую без использования int?
Можно написать собственную функцию для преобразования, используя алгоритм деления на основание. Однако встроенные средства Python являются наиболее эффективными и предпочтительными. Тем не менее, для учебных целей или при необходимости работы с системами, выходящими за пределы 36 (например, base64), такой подход полезен.
def to_base(num, base):
digits = '0123456789abcdefghijklmnopqrstuvwxyz'
res = ''
while num > 0:
res = digits[num % base] + res
num //= base
return res or '0'
print(to_base(255, 16)) # ff
print(to_base(255, 2)) # 11111111
ff 11111111
Как обработать возможные ошибки ввода при преобразовании?
При передаче строки, содержащей символы, недопустимые для указанного основания, возникает исключение ValueError. Следует обернуть вызов в try-except.
def safe_int(s, base):
try:
return int(s, base)
except ValueError:
return None
print(safe_int('1g', 16)) # None (g недопустим в 16-ричной)
print(safe_int('1f', 16)) # 31
None 31
Типичные ошибки и их решения
- Ошибка: Попытка передать строку с префиксом в int() с указанным основанием, например int('0b1010', 2). Решение: использовать base=0 или удалить префикс.
- Ошибка: Указание основания вне диапазона 2-36 (или 0). Решение: проверять значение base.
- Ошибка: Попытка преобразовать число с плавающей точкой. Решение: int() не поддерживает строки с точкой; необходимо предварительно преобразовать в float, затем в int.
- Ошибка: Забыть, что bin(), oct(), hex() возвращают строки с префиксом, что может мешать при дальнейшей обработке. Решение: использовать форматирование f'{value:b}' без префикса.
Расширенные примеры и нестандартные сценарии
Ниже приведены примеры, демонстрирующие более сложные и редко встречающиеся задачи.
Преобразование из 36-ричной системы с произвольными символами
# Использование int с base=36
s = 'hello' # hello в 36-ричной? h=17, e=14, l=21, l=21, o=24 => значение
value = int(s, 36)
print(value) # 29234652 (вычислено)
# Обратно в 36-ричную строку с помощью пользовательской функции
def from_base(num, base):
chars = '0123456789abcdefghijklmnopqrstuvwxyz'
if num == 0:
return '0'
res = ''
while num:
res = chars[num % base] + res
num //= base
return res
print(from_base(value, 36)) # hello
29234652 hello
Работа с отрицательными числами
# int сохраняет знак
neg = int('-ff', 16)
print(neg) # -255
# Форматирование отрицательного числа
print(f'{-255:b}') # -11111111
# bin() для отрицательных возвращает строку с минусом и двоичным представлением без знака?
print(bin(-255)) # -0b11111111
-255 -11111111 -0b11111111
Преобразование с ведущими нулями
# Для фиксированной ширины поля
num = 15
print(f'{num:04b}') # 1111 -> '1111' (ширина 4, но недостаточно, не добавляет ведущий ноль? Спецификатор '04b' добавит ведущие нули до нужной ширины, но для двоичного 15 - '1111' уже 4 символа, не добавляет. Для 5: '0101'
print(f'{5:08b}') # '00000101'
print(f'{255:05x}') # '000ff'
1111 00000101 000ff
Использование пользовательского набора символов (например, base62)
import string
chars = string.digits + string.ascii_lowercase + string.ascii_uppercase # 62 символа
def encode62(num):
if num == 0:
return chars[0]
res = ''
while num:
res = chars[num % 62] + res
num //= 62
return res
print(encode62(123456789)) # Пример: 1x7s? вычислим
# Декодирование из base62
def decode62(s):
return sum(chars.index(c) * (62 ** i) for i, c in enumerate(reversed(s)))
print(decode62('1x7s')) # должно быть 123456789
1x7s 123456789
Преобразование с автоматическим определением основания (base=0)
# int с base=0 анализирует префиксы: 0b, 0o, 0x, иначе десятичная
print(int('0b1010', 0)) # 10
print(int('0o17', 0)) # 15
print(int('0xff', 0)) # 255
print(int('123', 0)) # 123 (десятичная)
# Если строка без префикса и base=0, предполагается десятичная, но можно указать? Да.
10 15 255 123
Обработка больших чисел (длинная арифметика)
# int в Python поддерживает произвольную точность
big = int('deadbeefcafe', 16)
print(big) # 244837814094590 (огромное)
# Обратно в 16-ричную с префиксом
print(hex(big)) # 0xdeadbeefcafe
244837814094590 0xdeadbeefcafe
Перевод числа в систему с основанием больше 36 (например, в base64)
# Для base64 часто используют символы A-Z, a-z, 0-9, +, /
import base64
# Однако преобразование числа в base64 строку не тривиально, обычно для данных.
# Покажем перевод числа в 64-ричную с помощью собственного алфавита из 64 символов.
chars64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
def to_base64(num):
if num == 0:
return chars64[0]
res = ''
while num:
res = chars64[num % 64] + res
num //= 64
return res
print(to_base64(12345)) # Пример
DH