Конвертация чисел в hex-строку в Python: эффективные решения и альтернативы
Основные подходы к переводу чисел в hex
Встроенная функция hex()
Как быстро перевести целое число в шестнадцатеричную строку с префиксом '0x'?
number = 255
hex_string = hex(number)
print(hex_string) # '0xff'шестнадцатеричное число python (преобразование числа в шестнадцатеричную систему в python)
Функция hex() принимает целое число и возвращает строку, начинающуюся с '0x', за которой следуют цифры в нижнем регистре. Это самый простой и эффективный способ, рекомендуемый для большинства задач.
- Ошибка TypeError: передача нецелого числа (например, float) вызывает исключение. Решение: предварительно преобразовать число к int, либо использовать другой метод (например, через struct для float).
- Отрицательные числа: hex(-1) вернет '-0x1'. Если требуется беззнаковое представление, можно использовать побитовую операцию с маской.
- Отсутствие контроля формата: нельзя убрать префикс или изменить регистр без дополнительных манипуляций. Для этого лучше подходят функции форматирования.
Форматирование строк с помощью format()
Как получить шестнадцатеричное представление без префикса или с заглавными буквами?
number = 255
# Без префикса, нижний регистр
hex_lower = format(number, 'x')
print(hex_lower) # 'ff'
# С префиксом 0x, нижний регистр
hex_with_prefix = format(number, '#x')
print(hex_with_prefix) # '0xff'
# Заглавные буквы
hex_upper = format(number, 'X')
print(hex_upper) # 'FF'
# Фиксированная ширина с дополнением нулями
hex_padded = format(number, '04X')
print(hex_padded) # '00FF'
Функция format() дает гибкий контроль над отображением. Спецификаторы 'x' (нижний регистр) и 'X' (верхний) позволяют управлять регистром, а символ '#' добавляет префикс '0x' или '0X'. Дополнительно можно задать минимальную ширину поля (например, '04X').
Возможные проблемы: если число отрицательное, префикс '#' не добавляет минус, минус выводится отдельно. Для больших чисел ширина может быть превышена, тогда дополнение не применяется.
Использование f-строк
Как компактно вставить шестнадцатеричное представление в строку?
number = 255
# Аналогично format() внутри f-строки
print(f"Число в hex: {number:#x}") # 'Число в hex: 0xff'
print(f"Без префикса: {number:x}") # 'Без префикса: ff'
print(f"Заглавные: {number:X}") # 'Заглавные: FF'
print(f"С дополнением: {number:04X}") # 'С дополнением: 00FF'
f-строки с синтаксисом {переменная:спецификатор} работают так же, как format(), но встроены прямо в строковый литерал. Это удобно для интерполяции.
Ошибки те же, что и у format(): передача нечислового значения вызовет TypeError.
Ручная реализация алгоритма деления на 16
Как понять внутренний механизм преобразования чисел в шестнадцатеричную систему?
def to_hex(n):
if n == 0:
return "0"
digits = "0123456789abcdef"
result = ""
while n > 0:
remainder = n % 16
result = digits[remainder] + result
n //= 16
return result
print(to_hex(255)) # 'ff'
print(to_hex(16)) # '10'
print(to_hex(0)) # '0'
Алгоритм заключается в многократном делении числа на 16 с записью остатков в обратном порядке. Этот метод неэффективен для продакшена, но полезен для обучения.
Проблемы: не обрабатывает отрицательные числа и дробные. Для отрицательных нужно учитывать знак или использовать дополнительный код. Не добавляет префикс.
Преобразование с помощью метода строки .format()
Как использовать строковый метод format() вместо глобальной функции?
number = 255
hex_string = "{:x}".format(number)
print(hex_string) # 'ff'
# с префиксом
hex_string = "{:#x}".format(number)
print(hex_string) # '0xff'
Метод str.format() является эквивалентом глобальной функции format(), но вызывается на строке-шаблоне. Результат идентичен.
Разницы с format() нет, но может быть удобнее при конструировании сложных шаблонов.
Расширенные примеры и нестандартные случаи
Преобразование списка целых чисел в шестнадцатеричные строки
numbers = [0, 16, 255, 1024, 65535]
hex_list = [hex(n) for n in numbers]
print(hex_list)
# ['0x0', '0x10', '0xff', '0x400', '0xffff']
['0x0', '0x10', '0xff', '0x400', '0xffff']
Применение: вывод дампов памяти, кодирование цветов, хеши.
Обратное преобразование hex-строки обратно в число
hex_str = "0xff"
number = int(hex_str, 16)
print(number) # 255
# без префикса
hex_str2 = "FF"
number2 = int(hex_str2, 16)
print(number2) # 255
255 255
Функция int() с указанием основания (16) корректно обрабатывает как строки с префиксом '0x', так и без него.
Получение беззнакового представления для отрицательных чисел
def to_hex_unsigned(n, bits=32):
# битовая маска
mask = (1 << bits) - 1
# приводим к беззнаковому виду
unsigned = n & mask
return f"{unsigned:#0{bits//4+2}x}"
print(to_hex_unsigned(-1, 32)) # 0xffffffff
print(to_hex_unsigned(-255, 16)) # 0xff01
0xffffffff 0xff01
Полезно при работе с сетевыми протоколами, низкоуровневыми данными.
Преобразование числа с плавающей точкой в hex (IEEE 754)
import struct
def float_to_hex(f):
# упаковываем в 8 байт (double) или 4 байта (float)
packed = struct.pack('>d', f) # big-endian double
return packed.hex()
print(float_to_hex(3.141592653589793))
# '400921fb54442d18'
400921fb54442d18
Метод через struct.pack дает точное шестнадцатеричное представление числа с плавающей точкой по стандарту IEEE 754.
Преобразование цвета RGB в шестнадцатеричную строку
r, g, b = 255, 128, 64
hex_color = f"#{r:02X}{g:02X}{b:02X}"
print(hex_color) # #FF8040
#FF8040
Часто используется в веб-дизайне.
Преобразование байтовой строки в hex с помощью bytes.hex()
data = b"Hello"
hex_str = data.hex()
print(hex_str) # 48656c6c6f
# метод bytearray
ba = bytearray([0, 255, 16])
print(ba.hex()) # 00ff10
48656c6c6f 00ff10
Методы bytes.hex() и bytearray.hex() возвращают шестнадцатеричное представление последовательности байтов без разделителей.
Генерация шестнадцатеричных чисел с произвольным префиксом
number = 255
# можно использовать replace после hex()
no_prefix = hex(number).replace('0x', '')
print(no_prefix) # ff
# или добавить свой префикс
custom = 'h' + no_prefix
print(custom) # hff
ff hff
Иногда требуется нестандартный префикс (например, 'h' в ассемблере).
Работа с очень большими числами
big = 2**256 - 1
hex_big = hex(big)
print(len(hex_big) - 2) # количество шестнадцатеричных цифр (64)
print(hex_big[:20] + '...')
# '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
64 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
hex() корректно работает с числами произвольной величины.
Обработка ошибок при вводе
def safe_hex(value):
try:
return hex(int(value))
except (ValueError, TypeError):
return None
print(safe_hex("123abc")) # None (не число)
print(safe_hex([1,2])) # None
None None
Важно обрабатывать исключения, если источник данных ненадёжен.