Двоичная система и байты

Предпосылки: нет.

Целые числа

Десятичная система привычна: десять цифр (0–9), потому что у человека десять пальцев. Но компьютер собран из электронных переключателей, а переключатель различает только два состояния — ток идёт или не идёт. Строить из таких элементов десятичную логику дорого и ненадёжно: пришлось бы различать десять уровней напряжения вместо двух. Проще принять ограничение и работать с двумя цифрами — 0 и 1. Из этих двух цифр компьютер строит всё остальное: числа, текст, изображения, программы.

Бит

Транзистор — основной элемент процессора — работает как переключатель: открыт или закрыт. Одно из двух состояний. Этого достаточно, чтобы хранить одну двоичную цифру. Такая минимальная единица информации называется бит (bit, сокращение от binary digit — «двоичная цифра»). Бит принимает значение 0 или 1. Меньшее количество информации записать нельзя.

Одного бита хватает, чтобы закодировать «да/нет», «вкл/выкл», «истина/ложь». Но для чисел больше 1, для букв, для координат — нужно больше битов. Как именно — зависит от того, как устроена позиционная система счисления.

Позиционная запись

В десятичной системе запись 349 означает: 3 сотни + 4 десятка + 9 единиц. Каждая позиция имеет вес — степень десятки:

349 = 3 × 10² + 4 × 10¹ + 9 × 10⁰
    = 300     + 40      + 9

Двоичная система работает точно так же, только основание — два, а не десять. Вес каждой позиции — степень двойки:

Позиция (справа)76543210
Вес1286432168421

Число 42 в двоичной записи: нужно разложить 42 на сумму степеней двойки.

42 = 32 + 8 + 2
   = 1×32 + 0×16 + 1×8 + 0×4 + 1×2 + 0×1

Запись: 00101010. Единицы стоят в позициях с весом 32, 8 и 2 — их сумма даёт 42. Нули — в остальных позициях. Проверка:

0×128 + 0×64 + 1×32 + 0×16 + 1×8 + 0×4 + 1×2 + 0×1
= 32 + 8 + 2
= 42

Обратное преобразование (из двоичной в десятичную) — просто подставляем единицы в таблицу весов и складываем.

Чтобы перевести число из десятичной в двоичную систему, есть способ, не требующий знания степеней двойки наизусть — последовательное деление на 2:

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. Дополняем нулями слева до 8 позиций: 00101010. Тот же результат.

Двоичная арифметика

Сложение в двоичной системе подчиняется тем же правилам, что и в десятичной. В десятичной: 7 + 8 = 15, записываем 5, переносим 1 в следующий разряд. В двоичной: 1 + 1 = 10 (два), записываем 0, переносим 1.

Правила для одного разряда:

0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10  (0, перенос 1)

Складываем 3 + 5. Три — 0011, пять — 0101:

    перенос:  1 1 1 0
              0 0 1 1   (3)
            + 0 1 0 1   (5)
            ---------
              1 0 0 0   (8)

Разряд за разрядом, справа налево: 1+1 = 10 (пишем 0, перенос 1). 1+0+перенос 1 = 10 (пишем 0, перенос 1). 0+1+перенос 1 = 10 (пишем 0, перенос 1). 0+0+перенос 1 = 1. Результат: 1000 = 8.

Процессор складывает числа именно так — разряд за разрядом с переносом. И вот почему двоичная арифметика удобна для электроники: чтобы сложить два десятичных разряда, нужно учесть 100 комбинаций (10×10 цифр), а для двух двоичных — всего 4 (2×2). Схему на 4 комбинации легко реализовать в транзисторах. Простота двоичной арифметики — одна из причин, по которой компьютеры используют именно два состояния. Переключатель на три стабильных состояния построить технически можно (такие системы — троичные — экспериментально создавались в 1950-х), но добавление третьего состояния резко усложняет каждый логический элемент, и выигрыш в плотности записи не компенсирует усложнение схемы.

От бита к байту

Один бит — 0 или 1 — слишком мал, чтобы представить что-то полезное. Буква алфавита — это минимум 5 бит (2⁵ = 32 варианта), но при этом нет места для цифр и знаков препинания. Нужна стандартная группа.

В 1950-х и начале 1960-х единого стандарта не было. CDC 6600 (1964) использовал 6-битные символы — 64 варианта, но строчные буквы уже не помещались. PDP-8 (1965) работал с 12-битными словами, удобными для вычислений, но избыточными для одного символа. Инженеры IBM в проекте 7030 Stretch (1961) попробовали компромисс — 8-битный «байт» (слово byte — намеренное изменение слова bite, «кусок», чтобы не путать с bit). Но стандартом 8 бит стали лишь с выходом IBM System/360 в 1964 году.

System/360 зафиксировал 8 бит как универсальную единицу. Почему именно 8? Два практических соображения:

Достаточный диапазон. 8 бит дают 2⁸ = 256 вариантов. Хватает для всех латинских букв (заглавных и строчных), цифр, знаков препинания и служебных кодов. 6 бит (64 варианта) — не хватало даже для строчных букв. 7 бит (128 вариантов) — достаточно для латиницы, но 8 бит дают ещё одно преимущество.

Степень двойки. 8 = 2³. Память компьютера — пронумерованный ряд ячеек; номер ячейки называется адресом. Когда размер ячейки — степень двойки, процессору проще вычислять адреса: вместо умножения достаточно сдвига битов (что это за операция — будет в побитовых операциях).

С 1964 года байт (byte) — группа из 8 бит — стал стандартной единицей хранения и адресации. Один байт хранит число от 0 (00000000) до 255 (11111111).

Единицы измерения объёма

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

ОбозначениеЗначениеТочное количество байт
1 КБ (KB)10³1 000
1 МБ (MB)10⁶1 000 000
1 ГБ (GB)10⁹1 000 000 000
1 ТБ (TB)10¹²1 000 000 000 000

Но в вычислительной технике «круглые» числа — степени двойки, а не десятки. 2¹⁰ = 1024, что близко к 1000. Исторически инженеры стали называть 1024 байта «килобайтом», хотя приставка «кило-» строго означает 1000. Разница в 2.4% казалась незначительной.

С ростом объёмов расхождение накапливается. Для мегабайтов: 2²⁰ = 1 048 576 vs 10⁶ = 1 000 000 — разница уже 4.9%. Для гигабайтов: 2³⁰ = 1 073 741 824 vs 10⁹ = 1 000 000 000 — 7.4%. Производитель диска маркирует его как 500 GB (500 × 10⁹ байт). Операционная система делит на 2³⁰ и показывает 465 GiB. Те же самые байты, но разные шкалы — и пользователь думает, что ему недодали 35 гигабайт.

Для устранения путаницы в 1998 году IEC (International Electrotechnical Commission — Международная электротехническая комиссия) ввела двоичные приставки:

ОбозначениеЗначениеТочное количество байт
1 КиБ (KiB)2¹⁰1 024
1 МиБ (MiB)2²⁰1 048 576
1 ГиБ (GiB)2³⁰1 073 741 824
1 ТиБ (TiB)2⁴⁰1 099 511 627 776

KB, MB, GB — степени десятки (как в физике). KiB, MiB, GiB — степени двойки (как в памяти компьютера). На практике многие до сих пор говорят «мегабайт», имея в виду 2²⁰, — понять, какая шкала подразумевается, можно только из контекста.

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

Двоичная запись неудобна для человека: 11011110101011011011111011101111 — 32 цифры, в которых легко потеряться. Десятичная не помогает: по записи 3 735 928 559 невозможно сказать, какие биты установлены. Нужна компактная запись, которая сохраняет прямую связь с битами.

Шестнадцатеричная система (hexadecimal, hex) использует 16 цифр: 0–9, далее A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Одна hex-цифра кодирует ровно 4 бита (2⁴ = 16 вариантов). Это значит, что любую группу из 4 бит можно записать одним символом:

ДвоичнаяHexДесятичная
000000
000111
001022
001133
010044
010155
011066
011177
100088
100199
1010A10
1011B11
1100C12
1101D13
1110E14
1111F15

Один байт (8 бит) записывается ровно двумя hex-цифрами. Число 42 (двоичное 00101010) — hex 2A: первая тетрада 0010 = 2, вторая 1010 = A. Четыре байта — 8 hex-цифр вместо 32 двоичных.

Запись 0xDEADBEEF — 32-битное число, часто используемое в отладке как маркер неинициализированной памяти. Префикс 0x — общепринятый способ отличить hex от десятичной записи.

0xDEADBEEF:

  D    E    A    D    B    E    E    F
 1101 1110 1010 1101 1011 1110 1110 1111

32 бита, но записаны 8 читаемыми символами. Перевод мгновенный: каждая hex-цифра — независимая группа из 4 бит.

Hex повсеместен: адреса памяти, коды цветов в вебе (#FF5733), MAC-адреса сетевых карт, содержимое файлов в hex-редакторе. Везде, где важно видеть структуру на уровне байтов и полубайтов (полубайт из 4 бит называют ниббл, nibble — «маленький кусочек»).

Одни и те же биты — разный смысл

Восемь бит 01000001 хранятся в памяти одинаково. Но что они означают — зависит от того, кто их читает:

     Биты в памяти: 01000001

     Программа-калькулятор видит:  целое число 65
     Текстовый редактор видит:    букву 'A'

Целое число 65 — потому что 0×128 + 1×64 + 0×32 + 0×16 + 0×8 + 0×4 + 0×2 + 1×1 = 65.

Буква ‘A’ — потому что в таблице ASCII (American Standard Code for Information Interchange — «американский стандартный код для обмена информацией», 1963) буква A имеет код 65. ASCII задаёт соответствие между числами 0–127 и символами: 65 = ‘A’, 66 = ‘B’, 48 = ‘0’, 32 = пробел. Подробнее о кодировках символов — в отдельной заметке.

Сами биты не несут информации о своём типе. 01000001 — это просто восемь переключателей в определённых состояниях. Число, символ или что-то иное — решает программа, которая эти биты читает. Если программа ошибётся и прочитает текст как числа — результат будет бессмысленным, но компьютер не возразит. Для него всё — цепочки нулей и единиц.


Восемь бит дают 256 вариантов — от 00000000 (0) до 11111111 (255). Для небольших положительных чисел этого хватает. Но температура бывает ниже нуля, координата — левее начала, баланс — в минусе. Как записать отрицательное число, имея только нули и единицы, — тема следующей заметки.

Sources

  • Petzold, C., 2000, Code: The Hidden Language of Computer Hardware and Software. Microsoft Press.
  • Patterson, D., Hennessy, J., 2013, Computer Organization and Design. 5th ed. Morgan Kaufmann.
  • Mackenzie, C., 1980, Coded Character Sets, History and Development. Addison-Wesley.

Целые числа