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



...на главную страницу

Зачем был нужен дополнительный код?

Изобретение обратного и дополнительного кода возникло из-за желания сэкономить деньги при построении арифметико-логических устройств (АЛУ) вычислительных машин. В те далекие времена, когда даже самый слабенький компьютер занимал помещение в несколько комнат, каждый логический элемент, а тем более узел стоил существенных денег. Для того чтобы выполнить арифметическую операцию сложения, в АЛУ компьютера имеется специальный узел - сумматор, а для того чтобы выполнить вычитание, казалось бы, требуется "вычитатор", что влечет за собой дополнительные деньги. И тогда создатели первых компьютеров нашли способ производить операцию вычитания с помощью сумматора, используя для этого дополнительный код числа. То есть операция вычитания была заменена операцией сложения, где вычитаемое представлялось в дополнительном коде.

Как получить дополнительный код?

Давайте посмотрим, как получается дополнительный код для двоичной системы счисления. Вначале зададимся разрядностью регистра, в котором будет храниться наше число. Пусть, для примера, мы будем работать с 8-ми разрядными числами. Возьмем, опять же для примера, число двенадцать и запишем его в двоичной системе счисления: 1100. Теперь впишем его в 8-ми разрядный регистр, где старшие, незадействованные в числе, разряды имеют нулевое значение (нумерация разрядов начинается с нуля).

Разр.76543210
12 00001100

Такая запись соответствует 8-ми разрядному прямому коду числа двенадцать. А теперь проинвертируем все разряды регистра, т.е. заменим 0 на 1 и 1 на 0. и получим обратный код.

Разр.76543210
12обр 11110011

Прибавив к числу в обратном коде единицу, получаем искомый дополнительный код.

(красным цветом показаны переносы в соответствующий разряд)
Разр.c76543210
11
12обр11110011
+1
12доп11110100

Попробуем выполнить операцию вычитания нашего числа (двенадцать) из двадцати девяти с помощью сложения. Для этого впишем двоичное представление числа двадцать девять в 8-ми разрядный регистр и прибавим к нему дополнительный код, полученный ранее из числа двенадцать. Возникающий при этом перенос из самого старшего разряда игнорируем.

Разр.c76543210
111111
2900011101
12доп11110100
1700010001

Мы видим, что результирующая сумма есть двоичное число семнадцать и это действительно соответствует разности чисел двадцать девять и двенадцать.


Представление чисел с разными знаками

Давайте посмотрим на последний пример с математической точки зрения. Что мы видим? Мы к числу 29 прибавили нечто непонятное и получили 17, то есть 29+x=17. Решив последнее уравнение, мы видим, что "x" - это не что иное, как число "-12" (минус двенадцать). Оказывается, формируя дополнительный код от некоторого числа, мы получаем число противоположное по знаку исходному. Этот факт подтолкнул создателей компьютеров к естественной и очень эффективной модели представления отрицательных чисел, да и вообще чисел со знаком.

Идея состояла в том, чтобы хранить и обрабатывать положительные числа в прямом коде, а отрицательные в дополнительном. Необходимо было только как-то различать какое число перед нами положительное или отрицательное. Давайте, для наглядности сравним, как выглядят регистры с положительными числами и регистры с соответствующими им отрицательными числами, записанными в дополнительном коде.

Число Код
300000011
500000101
900001001
-311111101
-511111011
-911110111

Из анализа таблицы видно, что положительные числа начинаются с нулей, а отрицательные с единиц, что и позволяет в нашем примере отличать их по знаку. Но мы выбрали, для примера, небольшие положительные числа, в старшем разряде регистра которых изначально нет единицы. Но для числа "212" и соответственно "-212" это правило уже не срабатывает, так как число 212 изначально в старшем разряде регистра содержит единицу 21210 = 110101002.

Разр.76543210
212 11010100

Однако, наша модель чисел с разными знаками всегда будет работать, если запретить пользоваться числами, модуль которых содержит единицу в старшем разряде регистра. Для 8-ми разрядного регистра это числа, модуль которых не превышает 127. Старший разряд регистра, при этом, просто указывает знак и поэтому, в данной модели представления чисел, его называют знаковым разрядом.


Сложение чисел с разными знаками

Рассмотрим пример сложения чисел с разными знаками, используя описанную выше модель представления чисел. Где старший разряд регистра указывает знак числа (ноль для положительного, единица для отрицательного) , а само отрицательное число представляется в дополнительном коде. Сложим, для примера, восьмиразрядные числа "21" (двадцать один) и "-30" (минус тридцать).

Переведем их модули в двоичную систему счисления и запишем в 8-ми разрядные регистры. 2110 = 101012 ; 3010 = 111102

Разр.76543210
21 00010101

Разр.76543210
30 00011110

Чтобы получить число противоположное, по знаку, числу "30" возьмем от последнего дополнительный код. Сначала получим обратный код, инвертируя все разряды числа.

Разр.76543210
30обр11100001

Теперь прибавим единицу и получим дополнительный код.

Разр.c76543210
1
30обр11100001
+1
30доп11100010

Мы получили машинное представление числа "-30" (минус тридцать), теперь сложим эти числа (21 и -30).

Разр.c76543210
2100010101
30доп11100010
C11110111

Проанализируем полученный результат. Мы видим, что в старшем (знаковом) разряде результата содержится единица, следовательно, результат есть число отрицательное и поэтому представлено оно в дополнительном коде. Значение этого числа сразу неочевидно и чтобы понять, что это за число, нам необходимо узнать его модуль.

Из курса школьной математики известно, что модуль положительного числа есть само число, а модуль отрицательного числа есть число ему противоположное. Поэтому нам нужно получить число противоположное результату, а это мы уже знаем как сделать, нужно взять от него дополнительный код.

Проделаем это по известной схеме - проинвертируем каждый разряд C = 11110111 и получим Ci = 00001000. Теперь прибавим единицу.

Разр.c76543210
Сi00001000
+1
900001001

Ну вот, модуль числа результата есть "9" (девять), а сам результат соответственно "-9", что конечно же является правильным решением поставленной задачи: 21+(-30)= -9.

Рассмотрим еще пример на сложение, вычислим "-30" (минус тридцать) плюс "40" (сорок) . Код для числа "-30" у нас уже есть, а число "40" в двоичной системе есть "101000". Так как оно положительное , то запишем его в прямом 8-ми разрядном коде и прибавим к коду числа "-30".

Разр.c76543210
111
30доп11100010
4000101000
1000001010

Анализируя результат, мы видим, что старший знаковый разряд равен нулю, следовательно, результат есть число положительное и значит представлено оно в прямом коде, т.е. десять, что опять-таки является правильным решением поставленной задачи: -30+40= 10.

Итоги, уточнеия и обобщения о кодах

Давайте теперь уточним и обобщим все понятия, которыми мы пользовались, рассматривая вышеприведенные примеры. Итак, прежде всего, что такое код числа вообще и чем он отличается от самого числа? Код числа - это модель представления числа в цифровом устройстве. Например, в компьютере.

Главным параметром любого кода является его разрядность. В рассмотренных выше примерах мы пользовались 8-ми разрядными кодами. Обратите внимание, что разрядность кода - это не то, что в математике называют разрядностью числа. Например, двоичное число три (11) двух разрядное, число пять (101) трех, десять (1010) четырех разрядное. Но все они могут быть представлены некоторым 8-ми разрядным кодом. При этом отсутствующие старшие разряды числа, в коде, представляются нулями. Очевидно, что мы не сможем в некотором коде представить число, разрядность которого больше разрядности кода. Поэтому специалисты по вычислительной технике, в своей профессиональной деятельности, под разрядностью чисел понимают разрядность кода.

Кроме того, прежде чем кодировать числа, мы должны определиться, а какое собственно подмножество чисел мы собираемся кодировать? Если это натуральные числа, то потребуется один способ кодирования, кстати, самый простой. Для целых чисел уже нужно как-то кодировать знак числа и его модуль, а для кодирования рациональных чисел нужны еще более сложные коды. Так вот, прямой обратный и дополнительный код - это модели представления целых чисел, как положительных, так и отрицательных. Примеры записи некоторых чисел во всех трех восьмиразрядных кодах показаны в таблице ниже.

Число Прямой код Обратный код Дополнительный
код
0000000000000000000000000
1000000010000000100000001
-1100000011111111011111111
5000001010000010100000101
-5100001011111101011111011
8000010000000100000001000
-8100010001111011111111000
120011110000111100001111000
-120111110001000011110001000
127011111110111111101111111
-127111111111000000010000001

Во всех трех кодах старший разряд указывает на знак числа и он равен единице, если число отрицательное и нулю в противном случае. Остальные разряды содержат представление модуля числа. Различие между кодами наблюдается именно в способах представления модуля. Для положительного числа модуль во всех трех кодах представляется одинаково - это просто естественная запись двоичного числа. Для отрицательных чисел, в обратном коде это просто поразрядная инверсия прямого кода, а в дополнительном - к обратному коду, как к числу, просто прибавляется единица.



...к списку решаемых задач