Лекция №10
Тема: «Прямой, обратный и дополнительный код числа»
Введение
Зачем был нужен дополнительный код?
Изобретение обратного и дополнительного кода возникло из-за желания сэкономить деньги при построении арифметико-логических устройств (АЛУ) вычислительных машин. В те далекие времена, когда даже самый слабенький компьютер занимал помещение в несколько комнат, каждый логический элемент, а тем более узел стоил существенных денег. Для того чтобы выполнить арифметическую операцию сложения, в АЛУ компьютера имеется специальный узел — сумматор, а для того чтобы выполнить вычитание, казалось бы, требуется «вычитатор», что влечет за собой дополнительные деньги. И тогда создатели первых компьютеров нашли способ производить операцию вычитания с помощью сумматора, используя для этого дополнительный код числа. То есть операция вычитания была заменена операцией сложения, где вычитаемое представлялось в дополнительном коде.
Как получить дополнительный код?
Давайте посмотрим, как получается дополнительный код для двоичной системы счисления. Вначале зададимся разрядностью регистра, в котором будет храниться наше число. Пусть, для примера, мы будем работать с 8-ми разрядными числами. Возьмем, опять же для примера, число двенадцать и запишем его в двоичной системе счисления: 1100. Теперь впишем его в 8-ми разрядный регистр, где старшие, незадействованные в числе, разряды имеют нулевое значение (нумерация разрядов начинается с нуля).
Разряд | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
12 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
Такая запись соответствует 8-ми разрядному прямому коду числа двенадцать. А теперь проинвертируем все разряды регистра, т.е. заменим 0 на 1 и 1 на 0. и получим обратный код.
Разряд | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
12 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 |
Прибавив к числу в обратном коде единицу, получаем искомый дополнительный код.
(красным цветом показаны переносы в соответствующий разряд)
Разр. | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | ||||||||
12обр | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | |
+ | 1 | ||||||||
12доп | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
Попробуем выполнить операцию вычитания нашего числа (двенадцать) из двадцати девяти с помощью сложения. Для этого впишем двоичное представление числа двадцать девять в 8-ми разрядный регистр и прибавим к нему дополнительный код, полученный ранее из числа двенадцать. Возникающий при этом перенос из самого старшего разряда игнорируем.
12 | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | 1 | 1 | 1 | 1 | ||||
29 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | |
12доп | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | |
17 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
Мы видим, что результирующая сумма есть двоичное число семнадцать и это действительно соответствует разности чисел двадцать девять и двенадцать.
Представление чисел с разными знаками
Давайте посмотрим на последний пример с математической точки зрения. Что мы видим? Мы к числу 29 прибавили нечто непонятное и получили 17, то есть 29+x=17. Решив последнее уравнение, мы видим, что «x» — это не что иное, как число «-12» (минус двенадцать). Оказывается, формируя дополнительный код от некоторого числа, мы получаем число противоположное по знаку исходному. Этот факт подтолкнул создателей компьютеров к естественной и очень эффективной модели представления отрицательных чисел, да и вообще чисел со знаком.
Идея состояла в том, чтобы хранить и обрабатывать положительные числа в прямом коде, а отрицательные в дополнительном. Необходимо было только как-то различать какое число перед нами положительное или отрицательное. Давайте, для наглядности сравним, как выглядят регистры с положительными числами и регистры с соответствующими им отрицательными числами, записанными в дополнительном коде.
Число | Код |
3 | 00000011 |
5 | 00000101 |
9 | 00001001 |
-3 | 11111101 |
-5 | 11111011 |
-9 | 11110111 |
Из анализа таблицы видно, что положительные числа начинаются с нулей, а отрицательные с единиц, что и позволяет в нашем примере отличать их по знаку. Но мы выбрали, для примера, небольшие положительные числа, в старшем разряде регистра которых изначально нет единицы. Но для числа «212» и соответственно «-212» это правило уже не срабатывает, так как число 212 изначально в старшем разряде регистра содержит единицу 21210 = 110101002.
Разр. | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
212 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
Однако, наша модель чисел с разными знаками всегда будет работать, если запретить пользоваться числами, модуль которых содержит единицу в старшем разряде регистра. Для 8-ми разрядного регистра это числа, модуль которых не превышает 127. Старший разряд регистра, при этом, просто указывает знак и поэтому, в данной модели представления чисел, его называют знаковым разрядом.
Сложение чисел с разными знаками
Рассмотрим пример сложения чисел с разными знаками, используя описанную выше модель представления чисел. Где старший разряд регистра указывает знак числа (ноль для положительного, единица для отрицательного) , а само отрицательное число представляется в дополнительном коде. Сложим, для примера, восьмиразрядные числа «21» (двадцать один) и «-30» (минус тридцать).
Переведем их модули в двоичную систему счисления и запишем в 8-ми разрядные регистры. 2110 = 101012 ; 3010 = 111102
Разр. | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
21 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 |
Разр. | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
30 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |
Чтобы получить число противоположное, по знаку, числу «30» возьмем от последнего дополнительный код. Сначала получим обратный код, инвертируя все разряды числа.
Разр. | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
30обр | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
Теперь прибавим единицу и получим дополнительный код.
Разр. | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | |||||||||
30обр | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | |
+ | 1 | ||||||||
30доп | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 |
Мы получили машинное представление числа «-30» (минус тридцать), теперь сложим эти числа (21 и -30).
Разр. | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
21 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | |
30доп | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | |
C | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 |
Проанализируем полученный результат. Мы видим, что в старшем (знаковом) разряде результата содержится единица, следовательно, результат есть число отрицательное и поэтому представлено оно в дополнительном коде. Значение этого числа сразу неочевидно и чтобы понять, что это за число, нам необходимо узнать его модуль.
Из курса школьной математики известно, что модуль положительного числа есть само число, а модуль отрицательного числа есть число ему противоположное. Поэтому нам нужно получить число противоположное результату, а это мы уже знаем как сделать, нужно взять от него дополнительный код.
Проделаем это по известной схеме — проинвертируем каждый разряд C = 11110111 и получим Ci = 00001000. Теперь прибавим единицу.
Разр. | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Сi | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | |
+ | 1 | ||||||||
9 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |
Ну вот, модуль числа результата есть «9» (девять), а сам результат соответственно «-9», что конечно же является правильным решением поставленной задачи: 21+(-30)= -9.
Рассмотрим еще пример на сложение, вычислим «-30» (минус тридцать) плюс «40» (сорок) . Код для числа «-30» у нас уже есть, а число «40» в двоичной системе есть «101000». Так как оно положительное, то запишем его в прямом 8-ми разрядном коде и прибавим к коду числа «-30».
Разр. | c | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | 1 | |||||||
30доп | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | |
40 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | |
10 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
Анализируя результат, мы видим, что старший знаковый разряд равен нулю, следовательно, результат есть число положительное и значит представлено оно в прямом коде, т.е. десять, что опять-таки является правильным решением поставленной задачи: -30+40= 10.
Итоги, уточнеия и обобщения о кодах
Давайте теперь уточним и обобщим все понятия, которыми мы пользовались, рассматривая вышеприведенные примеры. Итак, прежде всего, что такое код числа вообще и чем он отличается от самого числа? Код числа — это модель представления числа в цифровом устройстве. Например, в компьютере.
Главным параметром любого кода является его разрядность. В рассмотренных выше примерах мы пользовались 8-ми разрядными кодами. Обратите внимание, что разрядность кода — это не то, что в математике называют разрядностью числа. Например, двоичное число три (11) двух разрядное, число пять (101) трех, десять (1010) четырех разрядное. Но все они могут быть представлены некоторым 8-ми разрядным кодом. При этом отсутствующие старшие разряды числа, в коде, представляются нулями. Очевидно, что мы не сможем в некотором коде представить число, разрядность которого больше разрядности кода. Поэтому специалисты по вычислительной технике, в своей профессиональной деятельности, под разрядностью чисел понимают разрядность кода.
Кроме того, прежде чем кодировать числа, мы должны определиться, а какое собственно подмножество чисел мы собираемся кодировать? Если это натуральные числа, то потребуется один способ кодирования, кстати, самый простой. Для целых чисел уже нужно как-то кодировать знак числа и его модуль, а для кодирования рациональных чисел нужны еще более сложные коды. Так вот, прямой обратный и дополнительный код — это модели представления целых чисел, как положительных, так и отрицательных. Примеры записи некоторых чисел во всех трех восьмиразрядных кодах показаны в таблице ниже.
Число | Прямой код | Обратный код | Дополнительный код |
0 | 00000000 | 00000000 | 00000000 |
1 | 00000001 | 00000001 | 00000001 |
-1 | 10000001 | 11111110 | 11111111 |
5 | 00000101 | 00000101 | 00000101 |
-5 | 10000101 | 11111010 | 11111011 |
8 | 00001000 | 00001000 | 00001000 |
-8 | 10001000 | 11110111 | 11111000 |
120 | 01111000 | 01111000 | 01111000 |
-120 | 11111000 | 10000111 | 10001000 |
127 | 01111111 | 01111111 | 01111111 |
-127 | 11111111 | 10000000 | 10000001 |
Во всех трех кодах старший разряд указывает на знак числа и он равен единице, если число отрицательное и нулю в противном случае. Остальные разряды содержат представление модуля числа. Различие между кодами наблюдается именно в способах представления модуля. Для положительного числа модуль во всех трех кодах представляется одинаково — это просто естественная запись двоичного числа. Для отрицательных чисел, в обратном коде это просто поразрядная инверсия прямого кода, а в дополнительном — к обратному коду, как к числу, просто прибавляется единица.