Преобразование систем счисления -- двоичная, десятичная, шестнадцатеричная

На этой лекции вы освоите методы преобразования между тремя системами счисления и поймёте, почему шестнадцатеричная система — "лучшее сокращение" для двоичной.


Аналогия из реальной жизни: несколько систем счисления

Разные системы счисления похожи на разные "единицы измерения".

Люди привыкли к десятичной системе, точно так же, как они привыкли измерять рост в "метрах".

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

Шестнадцатеричная система, с другой стороны, — это инженерное «сокращение», позволяющее записывать длинный двоичный код более компактно.

Например: если слово "EXAMPLE" записать на трёх «языках»:

  • Десятичная: человеческий язык:82 85 78 79 79 66
  • Двоичная: машинный язык:01010010 01010101 01001110 01001111 01001111 01000010
  • Шестнадцатеричная стенография:52 55 4E 4F 4F 42

То же выражение в двоичной системе в 4 раза длиннее, чем в шестнадцатеричной.

Вот почему нам нужно изучать перевод чисел между системами счисления.


Суть систем счисления: разложение по весам

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

Возьмём число 42 в качестве примера и посмотрим, как оно интерпретируется в каждой из трёх систем счисления:

baseОснованиеДоступные цифрыПредставляетРазложение по весам
decimal100 ~ 9424 x 101 + 2 x 100 = 42
двоичная20, 11010101x25+0x24+1x23+0x22+1x21+0x20 = 42
Шестнадцатеричная160~9, A~F2A2 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 в двоичную систему.

Метод довольно механический:

  1. Разделите 42 на 2; частное — 21, остаток0
  2. Разделите 21 на 2; частное равно 10, остаток1
  3. Разделите 10 на 2; частное равно 5, остаток0
  4. Разделите 5 на 2, частное 2, остаток1
  5. Разделите 2 на 2, частное 1, остаток0
  6. Разделите 1 на 2, частное 0, остаток1
  7. Прочитайте остатки снизу вверх:101010
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):

Position543210
двоичный бит101010
Вес (2^n)32168421
бит x вес1x320x161x80x41x20x1

1x32 + 0x16 + 1x8 + 0x4 + 1x2 + 0x1 = 42


Шестнадцатеричная система: «сокращённая запись» для двоичного кода

Самая большая проблема двоичной системы —Слишком длинная запись。

Для 8-битного значения нужно записать 8 цифр, а для 32-битного значения — 32 цифры.

Это неудобно для чтения человеком и подвержено ошибкам.

Шестнадцатеричная система решает эту проблему благодаря важному математическому совпадению:

24= 16 → каждые 4 двоичных бита точно соответствуют 1 шестнадцатеричной цифре

Таблица сопоставления 4 двоичных битов с 1 шестнадцатеричной цифрой

Двоичное (4 бита)decimalШестнадцатеричнаяДвоичное (4 бита)decimalШестнадцатеричная
000000100088
000111100199
001022101010A
001133101111B
010044110012C
010155110113D
011066111014E
011177111115F

Эта таблица — основа шестнадцатеричной системы.

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

Пример: преобразование двоичного числа 11111111 в шестнадцатеричное

8 двоичных битов делятся на две группы по 4 бита в каждой:

1111 = F    1111 = F→ Результат:0xFF

В программировании,0xПрефикс обозначает шестнадцатеричный формат (например,0xFF),0bПрефикс обозначает двоичный формат (например,0b11111111). Эти префиксы сообщают компилятору: это не десятичное число.


Интерактивная демонстрация: синхронный конвертер с тремя столбцами

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

Введите значение в любой столбец, два других столбца автоматически синхронизируются и обновятся.

Обратите внимание на выделенные цветные блоки под столбцом двоичных чисел — они показываютвзаимосвязь: 4 бита на группу соответствуют 1 шестнадцатеричной цифре.

Decimal

Основание=10, цифры=0~9

Binary

Основание=2, цифры=0,1

Шестнадцатеричная Hex

Основание=16, цифры=0~F

Попробуйте: введите 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 битами).

Другие расширения