Представление отрицательных чиселДополнительный код
Пусть имеется 3-разрядное десятичное число со знаком. Представим его в следующем виде:
-добавим слева еще одну цифру -знак числа, принимающую всего два значения: 0 -плюс, 1 -минус;
-положительные числа представляются обычным образом;
-каждая цифра отрицательного числа заменяется на дополнение ее до n-1, где n -основание системы счисления. Для десятичной системы -это дополнение до 9, то есть цифра, которая в сумме с исходной дает 9;
-к полученному числу добавляется 1.
Такое представление отрицательных чисел называется дополнительным кодом. Он обладает одним замечательным свойством: сложение чисел в дополнительном коде по правилам сложения целых без знака дает корректный результат, который также получается в дополнительном коде. Убедимся в этом:
.
- 3 8 6 - отрицательное число
1 6 1 3 - дополнение каждой цифры до 9
1 6 1 4 - добавление 1
___________________________________________
512 - 386 =
0 5 1 2
+ 1 6 1 4
_______
2 1 2 6 - для знака используется 0 или 1
0 1 2 6 (переполнение)
___________________________________________
119 - 386 =
0 1 1 9
+ 1 6 1 4
_______
1 7 3 3 - результат в дополнительном коде
- 2 6 6 - дополнение каждой цифры до 9
- 2 6 7 - добавление 1
Если внимательно присмотреться, то дополнение каждой цифры до 9 имеет некоторую аналогию с вычитанием. Но как бы там ни было, получаем следующий результат: вычитание или же сложение чисел со знаком заменяется операцией сложения, выполненной для беззнаковых чисел.
В двоичной системе счисления дополнение каждой цифры выглядит как инвертирование двоичного разряда, то есть замена 0 на 1 и наоборот.
Если же знак числа представляется старшим разрядом машинного слова, то получается простой способ представления отрицательного числа:
-взять абсолютное значение числа в двоичной системе;
-инвертировать все разряды, включая знаковый; -добавить 1.
Ту же самую последовательность операций нужно выполнить, чтобы получить из дополнительного кода абсолютное значение отрицательного числа. Сказанное проиллюстрируем примером в двоичной системе, хотя в дальнейшем будем использовать для этих целей шестнадцатеричную.
.
положительное число
15 - знаковый разряд
14-0 - абсолютное значение числа в двоичной системе
_______________________________________
0 0 0 0 0 1 1 0 1 1 0 1 1 0 0 0
_______________________________________
+ 0 6 D 8
.
отрицательное число в дополнительном коде
_______________________________________
1 1 1 1 1 0 0 1 0 0 1 0 0 1 1 1 инверсия машинного слова
_______________________________________
F 9 2 7
_______________________________________
1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 0 добавление 1
_______________________________________
F 9 2 8
Все эти нюансы вообще-то не важны для программиста, который знает, что для любой целой переменной арифметические операции будут выполняться корректно, будь то целое со знаком или без него. Но кроме этого в программе возможны преобразования знаковой формы представления в беззнаковую, и для их использования нужно знать, как "выглядят" отрицательные и положительные числа:
.
Целое со знаком Значение в дополнительном коде
0 0
1 1
... ...
+32766 0x7FFE
+32767 0x7FFF
-1 0xFFFF
-2 0xFFFE
-16 0xFFF0
-32767 0x8001
не определено (-0) 0x8000
Как видим, положительные числа представлены аналогично беззнаковым. Машинное слово со всеми разрядами, установленными в 1, соответствует значению -1, а затем по убыванию - -2,-3 и т.д..
В заключение посмотрим, как выглядит операция вычитания в шестнадцатеричной системе. Единственная техническая проблема здесь заключается в получении дополнения шестнадцатеричных цифр, что впрочем можно сделать простой инверсией двоичных разрядов в тетраде:
.
Дополнение 6 = Дополнение 0110 = 1001 = 9
.
24-66 = 0x18-0x42 = 0x18+(-0x42) = 0x18+0xFFBD+1 =
.
0x18+0xFFBE = 0xFFD6 = -(0x0029 + 1) = -0x2A = - 42