Синтаксис Java · Урок 6/9
67%
⏱ 5 минут чтения

Прямой, обратный и дополнительный код

Как целочисленные числа хранятся в памяти компьютера — и чем отличаются три схемы двоичного кодирования.

Как байт выглядит в памяти

Числа в памяти компьютера хранятся в двоичном виде. Тип byte в Java занимает 8 бит. Каждый бит хранит 0 или 1:

0
0
0
1
0
1
0
1
знак
бит 6
бит 5
бит 4
бит 3
бит 2
бит 1
бит 0

В знаковых целых числах старший (самый левый) бит является знаковым битом: 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)

Для получения обратного кода инвертируются все биты числа — включая знаковый бит. Ни один бит не является исключением.

+4 (исходное)
0
0
0
0
0
1
0
0
−4 (обратный код)
1
1
1
1
1
0
1
1

В обратном коде сохраняется проблема двух нулей. Значение 1 111 1111 представляет −0, что отличается от +0 (0 000 0000). Дополнительный код решает эту проблему.

Дополнительный код (two's complement)

Именно так Java (и практически все современные процессоры) хранят отрицательные целые числа. Дополнительный код устраняет проблему двойного нуля и позволяет выполнять сложение и вычитание одной аппаратной операцией независимо от знака.

Алгоритм перевода положительного числа в дополнительный код

1

Инвертируются все биты — включая знаковый бит (это даёт обратный код):

+4
0
0
0
0
0
1
0
0
обратный код
1
1
1
1
1
0
1
1
2

К результату прибавляется единица:

обратный код
1
1
1
1
1
0
1
1
+ 1

доп. код (−4)
1
1
1
1
1
1
0
0
Проверка: Дополнительный код числа −4 равен 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
Важный вывод: В дополнительном коде ноль имеет единственное представление. Это освобождает одну битовую комбинацию для дополнительного отрицательного значения — 8-битное знаковое целое охватывает диапазон от −128 до +127, а не симметричный −127 до +127.

Диапазоны целочисленных типов в Java

Все четыре целочисленных примитива Java используют дополнительный код. Асимметрия диапазона (одно дополнительное отрицательное значение) — прямое следствие устранения −0.

byte · 8 бит
−128
до
+127
short · 16 бит
−32 768
до
+32 767
int · 32 бита
−2 147 483 648
до
+2 147 483 647
long · 64 бита
−9 223 372 036 854 775 808
до
+9 223 372 036 854 775 807

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

‹ Предыдущий урок Следующий урок ›