Прямой, обратный и дополнительный код
Как целочисленные числа хранятся в памяти компьютера — и чем отличаются три схемы двоичного кодирования.
Как байт выглядит в памяти
Числа в памяти компьютера хранятся в двоичном виде. Тип byte в Java занимает 8 бит. Каждый бит хранит 0 или 1:
В знаковых целых числах старший (самый левый) бит является знаковым битом: 0 — положительное, 1 — отрицательное. Оставшиеся 7 бит кодируют величину числа. Это основа для всех трёх схем кодирования.
Прямой код (sign-magnitude)
Наиболее интуитивная кодировка. Знаковый бит указывает направление, а оставшиеся 7 бит хранят точное двоичное значение величины числа.
| Десятичное | Прямой код (8 бит) |
|---|---|
| 3 | 0 000 0011 |
| 2 | 0 000 0010 |
| 1 | 0 000 0001 |
| 0 | 0 000 0000 |
| −0 | 1 000 0000 |
| −1 | 1 000 0001 |
| −2 | 1 000 0010 |
0 000 0000 (+0) и 1 000 0000 (−0). Арифметические схемы вынуждены обрабатывать это как особый случай, что усложняет аппаратную реализацию. Современные процессоры используют дополнительный код.Обратный код (one's complement)
Для получения обратного кода инвертируются все биты числа — включая знаковый бит. Ни один бит не является исключением.
В обратном коде сохраняется проблема двух нулей. Значение 1 111 1111 представляет −0, что отличается от +0 (0 000 0000). Дополнительный код решает эту проблему.
Дополнительный код (two's complement)
Именно так Java (и практически все современные процессоры) хранят отрицательные целые числа. Дополнительный код устраняет проблему двойного нуля и позволяет выполнять сложение и вычитание одной аппаратной операцией независимо от знака.
Алгоритм перевода положительного числа в дополнительный код
Инвертируются все биты — включая знаковый бит (это даёт обратный код):
К результату прибавляется единица:
1111 1100. Проверим: 1111 1100 + 0000 0100 = 0000 0000 (переполнение отбрасывается) ✓Сводная таблица
| Десятичное | Прямой код | Обратный код | Дополнительный код |
|---|---|---|---|
| 0 | 0 000 0000 | 0 000 0000 | 0 000 0000 |
| −0 | 1 000 0000 | 1 111 1111 | — (нет −0) |
| −1 | 1 000 0001 | 1 111 1110 | 1 111 1111 |
| −2 | 1 000 0010 | 1 111 1101 | 1 111 1110 |
| −3 | 1 000 0011 | 1 111 1100 | 1 111 1101 |
| −4 | 1 000 0100 | 1 111 1011 | 1 111 1100 |
| −5 | 1 000 0101 | 1 111 1010 | 1 111 1011 |
Диапазоны целочисленных типов в Java
Все четыре целочисленных примитива Java используют дополнительный код. Асимметрия диапазона (одно дополнительное отрицательное значение) — прямое следствие устранения −0.
Video Explanation
Prefer video format? Watch this lesson with examples and explanations.