Преобразование систем счисления -- двоичная, десятичная, шестнадцатеричная
На этой лекции вы освоите методы преобразования между тремя системами счисления и поймёте, почему шестнадцатеричная система — "лучшее сокращение" для двоичной.
Аналогия из реальной жизни: несколько систем счисления
Разные системы счисления похожи на разные "единицы измерения".
Люди привыкли к десятичной системе, точно так же, как они привыкли измерять рост в "метрах".
Компьютеры используют двоичную систему, словно мыслят категориями "состояний переключателей".
Шестнадцатеричная система, с другой стороны, — это инженерное «сокращение», позволяющее записывать длинный двоичный код более компактно.
Например: если слово "EXAMPLE" записать на трёх «языках»:
- Десятичная: человеческий язык:82 85 78 79 79 66
- Двоичная: машинный язык:01010010 01010101 01001110 01001111 01001111 01000010
- Шестнадцатеричная стенография:52 55 4E 4F 4F 42
То же выражение в двоичной системе в 4 раза длиннее, чем в шестнадцатеричной.
Вот почему нам нужно изучать перевод чисел между системами счисления.
Суть систем счисления: разложение по весам
Принципы всех систем счисления абсолютно одинаковы —умножьте цифру в каждой позиции на степень основания, затем сложите всё вместе.。
Возьмём число 42 в качестве примера и посмотрим, как оно интерпретируется в каждой из трёх систем счисления:
| base | Основание | Доступные цифры | Представляет | Разложение по весам |
|---|---|---|---|---|
| decimal | 10 | 0 ~ 9 | 42 | 4 x 101 + 2 x 100 = 42 |
| двоичная | 2 | 0, 1 | 101010 | 1x25+0x24+1x23+0x22+1x21+0x20 = 42 |
| Шестнадцатеричная | 16 | 0~9, A~F | 2A | 2 x 161 + 10 x 160 = 42 |
Ключевое правило:«Основание» системы счисления определяет вес каждой цифры。
Десятичная система имеет основание 10, а позиционные веса — это степени 10.0=1, разряд десятков 101=10, разряд сотен 102=100.
Двоичная система имеет основание 2; веса справа налево: 1, 2, 4, 8, 16, 32, 64, 128.
Шестнадцатеричная система имеет основание 16, а веса справа налево: 1, 16, 256, 4096.
Как только вы поймёте «разложение по весам», все преобразования между системами счисления станут простыми. Единственное предложение, которое нужно запомнить: каждую цифру умножаем на основание, возведённое в степень позиции, а затем складываем результаты.
Способ 1: из десятичной в двоичную (повторное деление на 2 с записью остатков)
Предположим, вы хотите перевести десятичное число 42 в двоичную систему.
Метод довольно механический:
- Разделите 42 на 2; частное — 21, остаток0
- Разделите 21 на 2; частное равно 10, остаток1
- Разделите 10 на 2; частное равно 5, остаток0
- Разделите 5 на 2, частное 2, остаток1
- Разделите 2 на 2, частное 1, остаток0
- Разделите 1 на 2, частное 0, остаток1
- Прочитайте остатки снизу вверх:101010
Почему этот метод работает?
Суть двоичной системы: N = d0x20 + d1x21 + d2x22 + ...
Когда N делится на 2, остаток равен d0(младший значащий бит), а частное последовательно делится на 2, чтобы получить следующий бит.
Эта логика точно такая же, как «деление на 10, чтобы получить цифру единиц», которое вы изучали в начальной школе.
Метод 2: Из двоичной в десятичную (разложение по весам)
Перевод из двоичной обратно в десятичную ещё проще — просто сложите веса напрямую.
двоичная101010(Пронумеруйте позиции справа налево от 0 до 5):
| Position | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|
| двоичный бит | 1 | 0 | 1 | 0 | 1 | 0 |
| Вес (2^n) | 32 | 16 | 8 | 4 | 2 | 1 |
| бит x вес | 1x32 | 0x16 | 1x8 | 0x4 | 1x2 | 0x1 |
1x32 + 0x16 + 1x8 + 0x4 + 1x2 + 0x1 = 42
Шестнадцатеричная система: «сокращённая запись» для двоичного кода
Самая большая проблема двоичной системы —Слишком длинная запись。
Для 8-битного значения нужно записать 8 цифр, а для 32-битного значения — 32 цифры.
Это неудобно для чтения человеком и подвержено ошибкам.
Шестнадцатеричная система решает эту проблему благодаря важному математическому совпадению:
24= 16 → каждые 4 двоичных бита точно соответствуют 1 шестнадцатеричной цифре
Таблица сопоставления 4 двоичных битов с 1 шестнадцатеричной цифрой
| Двоичное (4 бита) | decimal | Шестнадцатеричная | Двоичное (4 бита) | decimal | Шестнадцатеричная |
|---|---|---|---|---|---|
| 0000 | 0 | 0 | 1000 | 8 | 8 |
| 0001 | 1 | 1 | 1001 | 9 | 9 |
| 0010 | 2 | 2 | 1010 | 10 | A |
| 0011 | 3 | 3 | 1011 | 11 | B |
| 0100 | 4 | 4 | 1100 | 12 | C |
| 0101 | 5 | 5 | 1101 | 13 | D |
| 0110 | 6 | 6 | 1110 | 14 | E |
| 0111 | 7 | 7 | 1111 | 15 | F |
Эта таблица — основа шестнадцатеричной системы.
Как только вы её запомните, любое преобразование из двоичной системы в шестнадцатеричную становится механической операцией «посмотреть в таблицу и взять цифру».
Пример: преобразование двоичного числа 11111111 в шестнадцатеричное
8 двоичных битов делятся на две группы по 4 бита в каждой:
В программировании,
0xПрефикс обозначает шестнадцатеричный формат (например,0xFF),0bПрефикс обозначает двоичный формат (например,0b11111111). Эти префиксы сообщают компилятору: это не десятичное число.
Интерактивная демонстрация: синхронный конвертер с тремя столбцами
Приведённый ниже конвертер позволяет наблюдать соответствие между тремя системами счисления в реальном времени.
Введите значение в любой столбец, два других столбца автоматически синхронизируются и обновятся.
Обратите внимание на выделенные цветные блоки под столбцом двоичных чисел — они показываютвзаимосвязь: 4 бита на группу соответствуют 1 шестнадцатеричной цифре.
Decimal
Binary
Шестнадцатеричная Hex
Попробуйте: введите 255 в десятичный столбец и обратите внимание, что в двоичном столбце все единицы, а в шестнадцатеричном — FF.
Это «максимальное значение одного байта» — как только вы это поймёте, многие концепции прояснятся.
Демонстрация кода: полное преобразование систем счисления
Пример
def decimal_to_binary(n):
"""Десятичное в двоичное: метод деления на 2 с остатком, показывающий все шаги"""
if n == 0:
return "0"
steps = []
original = n
while n > 0:
remainder = n % 2
quotient = n // 2
steps.append((n, quotient, remainder))
n = quotient
result = ''.join(str(r) for _, _, r in reversed(steps))
print(f"{original} преобразовано в двоичную систему:")
for val, quot, rem in steps:
print(f{val:3d} ÷ 2 = {quot:3d} остаток {rem})
print(f" → Результат: {result}")
return result
def binary_to_decimal(bin_str):
"""Перевод из двоичной в десятичную: метод взвешенного разложения"""
decimal = 0
length = len(bin_str)
print(fДвоичное число {bin_str}, разложенное по весам:)
for i, ch in enumerate(bin_str):
power = length - 1 - i
if ch == '1':
value = 2 ** power
decimal += value
print(fбит {power}: 1 x 2^{power} = {value})
print(f" → сумма: {decimal}")
return decimal
def bin_to_hex(bin_str):
"""Двоичное в шестнадцатеричное: поиск по таблице группами по 4 бита"""
while len(bin_str) % 4 != 0:
bin_str = '0' + bin_str
hex_map = {
'0000':'0','0001':'1','0010':'2','0011':'3',
'0100':'4','0101':'5','0110':'6','0111':'7',
'1000':'8','1001':'9','1010':'A','1011':'B',
'1100':'C','1101':'D','1110':'E','1111':'F'
}
result = ''
groups = []
for i in range(0, len(bin_str), 4):
group = bin_str[i:i+4]
hex_char = hex_map[group]
groups.append(f"{group} → {hex_char}")
result += hex_char
print(f"Двоичное {bin_str} в шестнадцатеричное:")
for g in groups:
print(f" {g}")
print(f" → 0x{result}")
return result
def hex_to_bin(hex_str):
"""Из шестнадцатеричной в двоичную: преобразовать каждую цифру в 4 бита"""
rev_map = {
'0':'0000','1':'0001','2':'0010','3':'0011',
'4':'0100','5':'0101','6':'0110','7':'0111',
'8':'1000','9':'1001','A':'1010','B':'1011',
'C':'1100','D':'1101','E':'1110','F':'1111'
}
hex_str = hex_str.upper()
result = ''
for ch in hex_str:
expanded = rev_map[ch]
result += expanded
print(f" {ch} → {expanded}")
# Удалить ведущие нули (но оставить хотя бы одну цифру)
result = result.lstrip('0') or '0'
print(f" → {result}")
return result
Комплексный тест: на основе ASCII-кода 82 символа EXAMPLE 'R'
print("=" * 50)
print(Тестовое значение: 82 (ASCII 'R' из EXAMPLE))
print("=" * 50)
bin_result = decimal_to_binary(82)
print(f"82 → двоичное: {bin_result}\n")
dec_result = binary_to_decimal(bin_result)
print()
hex_result = bin_to_hex(bin_result)
print()
print("Обратная проверка: шестнадцатеричное → двоичное")
hex_to_bin(hex_result)
print("\n" + "=" * 50)
print(Тестовое значение: 255 (максимальное значение байта))
print("=" * 50)
bin_255 = decimal_to_binary(255)
print(fДвоичное: {bin_255})
hex_255 = bin_to_hex(bin_255)
print(f"Шестнадцатеричное: 0x{hex_255}")
print(Примечание: двоичное представление числа 255 — это 8 битов, все равные 1, но шестнадцатеричное представление использует только 2 цифры, FF.)
Продвинутое: быстрое преобразование из шестнадцатеричной в десятичную
Вы уже знаете два метода преобразования в десятичную: один — разложение по весам (каждая шестнадцатеричная цифра умножается на степень 16), а другой — сначала преобразование в двоичную, а затем в десятичную.
Но есть более практичный метод —Использование двоичной системы как «промежуточного языка»。
Любое преобразование между системами счисления может использовать двоичную систему как мост:
Потому что прямое преобразование между десятичной и шестнадцатеричной системами требует больше вычислений, но преобразование каждой из них в двоичную и обратно очень просто.
Из десятичной в двоичную: делить на 2 и брать остаток.
Из шестнадцатеричной в двоичную: развернуть по таблице (каждая 1 цифра становится 4 битами).
Другие расширения