Освоение шестнадцатеричной системы: Python-инструменты и примеры
Шестнадцатеричная система счисления широко применяется в программировании для компактного представления бинарных данных, адресов памяти, цветов и хешей. В Python встроенные средства позволяют легко преобразовывать числа в 16-ричный формат и обратно, а также выполнять форматирование. В этой статье рассматриваются основные приёмы работы с основанием 16, типичные ошибки и способы их устранения.
Основные функции для работы с 16-ричными числами
Самым эффективным и простым способом является использование встроенных функций hex(), int(), format() и f-строк. Они покрывают большинство задач.
# Преобразование целого числа в шестнадцатеричную строку
num = 255
hex_str = hex(num)
print(hex_str) # '0xff'
# Преобразование шестнадцатеричной строки в целое число
hex_input = '1a'
value = int(hex_input, 16)
print(value) # 26
# Форматирование с заданным количеством цифр (без префикса)
print(f'{num:02x}') # 'ff'
print(f'{num:#010x}') # '0x000000ff'алгоритм перевода систем счисления python (алгоритм перевода систем счисления на python)
Функция hex() возвращает строку с префиксом '0x'. Для преобразования строки (с префиксом или без) в число используется int() с указанием основания 16. Форматирование через f-строки даёт гибкий контроль над выводом.
Типичные ошибки:
- Передача нестрокового значения в int() с основанием 16 – нужно убедиться, что аргумент строка.
- Использование недопустимых символов (например, 'g', 'z') – вызовет ValueError.
- Путаница с регистром: int('FF', 16) работает, а int('ff', 16) тоже.
Решение: применять try/except для обработки исключений и использовать all(c in '0123456789abcdefABCDEF' for c in s) для предварительной проверки.
Различные подходы к работе с 16-ричными данными
Как преобразовать целое число в шестнадцатеричную строку без префикса?
Для этого используется format() или f-строка с спецификатором x (нижний регистр) или X (верхний регистр).
n = 1000
low = format(n, 'x') # '3e8'
high = f'{n:X}' # '3E8'
print(low, high)перевод в любую систему счисления python код (перевод числа в любую систему счисления на python (код))
Такой подход удобен, когда префикс не нужен, например, для формирования URL-кодирования.
Проблема: при малых числах результирующая строка может быть пустой (для нуля) или однозначной. Решение – указать минимальное количество цифр, например f'{n:02x}'.
Как выполнить арифметические операции с числами, представленными в 16-ричном виде?
Сначала строки преобразуются в числа, выполняются вычисления, результат преобразуется обратно.
a_hex = 'a3'
b_hex = '2f'
a = int(a_hex, 16)
b = int(b_hex, 16)
sum_ = a + b
diff = a - b
print(f'{a_hex} + {b_hex} = {sum_:x}') # a3 + 2f = d2
print(f'{a_hex} - {b_hex} = {diff:x}') # a3 - 2f = 74
перевод в троичную систему счисления python (перевод числа в троичную систему счисления на python)
Аналогично выполняются умножение, деление и битовые операции.
Типичная ошибка: попытка сложить две строки напрямую – это приведёт к конкатенации. Всегда нужно явно преобразовывать в int.
Как получить шестнадцатеричное представление числа с фиксированным количеством цифр (например, для цветов RGB)?
Используется спецификатор с шириной поля и заполнителем.
r, g, b = 128, 200, 15
hex_color = f'#{r:02X}{g:02X}{b:02X}'
print(hex_color) # '#80C80F'шестнадцатеричная система счисления python (шестнадцатеричная система счисления в python)
Здесь 02X означает: два символа, буквы в верхнем регистре, незначащие нули добавляются слева.
Проблема: если число выходит за пределы одного байта (0..255), то 02X не обрежет его, а выведет больше цифр. Решение – предварительно применять маску value & 0xFF.
Как обработать ошибки при вводе некорректной шестнадцатеричной строки?
Рекомендуется использовать конструкцию try/except с перехватом ValueError.
def safe_hex_to_int(s):
try:
return int(s, 16)
except ValueError:
print(f'Ошибка: "{s}" не является допустимым 16-ричным числом')
return None
print(safe_hex_to_int('1g')) # Ошибка
print(safe_hex_to_int('ff')) # 255
Для дополнительной валидации можно проверить строку регулярным выражением ^[0-9a-fA-F]+$ или через all(), но try/except более идиоматично.
Типичная ошибка: забыть указать основание 16 в int() – тогда строка будет воспринята как десятичная, что приведёт к непредсказуемым результатам.
Как работать с шестнадцатеричными числами в разных системах контекстов (сеть, файлы)?
Часто данные приходят в виде байтов (например, MAC-адреса или хеши). Для преобразования байтов в hex-строку и обратно существуют методы bytes.hex() и bytes.fromhex().
mac_bytes = b'\xaa\xbb\xcc\xdd\xee\xff'
hex_mac = mac_bytes.hex() # 'aabbccddeeff'
formatted = ':'.join(f'{b:02X}' for b in mac_bytes) # 'AA:BB:CC:DD:EE:FF'
# Обратно
original = bytes.fromhex('aabbccddeeff')
print(original == mac_bytes) # True
Этот подход используется при работе с сетевыми пакетами, криптографией, сериализацией.
Проблема: bytes.fromhex() принимает строку только с чётным количеством символов и без пробелов. Если строка нечётная или содержит разделители, нужно предварительно очистить её (удалить ':', ' ' и т.д.).
Расширенные и неочевидные примеры работы с 16-ричными числами
Преобразование больших целых чисел
Python поддерживает целые числа произвольной точности, и 16-ричное представление может быть очень длинным.
big = 2**128
hex_big = hex(big)
print(hex_big)
# '0x100000000000000000000000000000000'
0x100000000000000000000000000000000
Обратное преобразование: int(hex_big, 16) вернёт исходное число.
Битовые операции с 16-ричными числами
Для наглядности битовых масок удобно использовать шестнадцатеричную запись.
a = 0xAB # 171
b = 0xCD # 205
print(f"a & b = {a & b:#x}") # 0x89
print(f"a | b = {a | b:#x}") # 0xcf
print(f"a ^ b = {a ^ b:#x}") # 0x46
print(f"~a = {~a & 0xFF:#x}") # 0x54 (маскируем младший байт)
a & b = 0x89 a | b = 0xcf a ^ b = 0x46 ~a = 0x54
Маскирование через 0xFF ограничивает результат одним байтом.
Проверка корректности 16-ричной строки без использования исключений
Можно применить регулярное выражение или метод all().
import re
def is_hex(s):
return bool(re.fullmatch(r'[0-9a-fA-F]+', s))
print(is_hex('1a2b')) # True
print(is_hex('1g2b')) # False
print(is_hex('')) # False
True False False
Этот способ быстрее, чем try/except, если ожидается много некорректных строк.
Преобразование RGB в шестнадцатеричный цветовой код
Часто используется в веб-разработке. Важно ограничить значения каждого канала диапазоном от 0 до 255.
def rgb_to_hex(r, g, b):
# обрезка до 0..255
r, g, b = (max(0, min(255, x)) for x in (r, g, b))
return f'#{r:02X}{g:02X}{b:02X}'
print(rgb_to_hex(255, 128, 64)) # '#FF8040'
print(rgb_to_hex(300, -10, 0)) # '#FF0000'
#FF8040 #FF0000
Работа с MAC-адресами
MAC-адрес состоит из 6 байтов, обычно разделённых двоеточием или дефисом.
mac_int = 0xAABBCCDDEEFF
mac_bytes = mac_int.to_bytes(6, 'big')
mac_str = ':'.join(f'{b:02X}' for b in mac_bytes)
print(mac_str) # 'AA:BB:CC:DD:EE:FF'
# Из строки обратно
parts = mac_str.split(':')
mac_bytes2 = bytes(int(p, 16) for p in parts)
mac_int2 = int.from_bytes(mac_bytes2, 'big')
print(hex(mac_int2)) # '0xaabbccddeeff'
AA:BB:CC:DD:EE:FF 0xaabbccddeeff
Вычисление хеша SHA-256 и его шестнадцатеричное представление
Модуль hashlib возвращает hexdigest автоматически.
import hashlib
data = b'Hello, world!'
hash_obj = hashlib.sha256(data)
hex_digest = hash_obj.hexdigest()
print(hex_digest)
# '315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3'
315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
Обратное преобразование (hex в bytes) делается через bytes.fromhex(hex_digest).
Кодирование байтовых данных в hex с помощью модуля binascii
Модуль binascii предоставляет низкоуровневые функции.
import binascii
data = b'Python'
hex_encoded = binascii.hexlify(data)
print(hex_encoded) # b'507974686f6e'
# Обратно
decoded = binascii.unhexlify(hex_encoded)
print(decoded) # b'Python'
b'507974686f6e' b'Python'
Результат hexlify – тоже байтовая строка, её можно декодировать в обычную строку через .decode().
Преобразование между 16-ричной строкой и целым числом с фиксированной длиной (например, для сериализации)
Иногда требуется представить число в hex с определённым количеством байт (например, 4 байта для IPv4).
ip_int = 0xC0A80101 # 192.168.1.1
# 4 байта, big-endian
ip_bytes = ip_int.to_bytes(4, 'big')
ip_hex = ip_bytes.hex()
print(ip_hex) # 'c0a80101'
# Обратно
ip_int_back = int.from_bytes(bytes.fromhex(ip_hex), 'big')
print(hex(ip_int_back)) # 0xc0a80101
c0a80101 0xc0a80101