Дополнительный код (представление числа)

Материал из Википедии — свободной энциклопедии

Перейти к: навигация, поиск

Дополнительный код (англ. two’s complement, иногда twos-complement) — наиболее распространенный способ представления отрицательных целых чисел в компьютерах. Он позволяет заменить операцию вычитания на операцию сложения, чем упрощает архитектуру ЭВМ. Дополнительный код отрицательного числа получается инвертированием двоичного числа и прибавлением к нему единицы.

Содержание

[править] Представление числа в дополнительном коде

При записи числа в дополнительном коде старший разряд является знаковым. Если его значение равно 0, то в остальных разрядах записано положительное двоичное число, совпадающее с прямым кодом. Если же знаковый разряд равен 1, то в остальных разрядах записано отрицательное двоичное число, преобразованное в дополнительный код. Для получения значения отрицательного числа все разряды, кроме знакового, инвертируются, а к результату добавляется единица. Обратное преобразование, то есть перевод из дополнительного в прямой код, осуществляется аналогично.

Двоичное 8-ми разрядное число со знаком может представлять любое целое в диапазоне от −128 до +127. Если старший разряд равен нулю, то наибольшее целое число, которое может быть записано в оставшихся 7 разрядах равно 27 − 1, что равно 127.

Примеры:

десятичный      8-битный двоичный 
             прямой     дополнительный
-------------------------------------
  0           00000000	  00000000
  1           00000001  00000001
 -1          -00000001  11111111
-10 	       -00001010  11110110

[править] Преобразование дополнительного кода

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

  1. Если число, записанное в прямом коде, положительное, то к нему дописывается старший (знаковый) разряд, равный 0, и на этом преобразование заканчивается;
  2. Если число, записанное в прямом коде, отрицательное, то все разряды числа инвертируются, а к результату прибавляется 1. К получившемуся числу дописывается старший (знаковый) разряд, равный 1.

Пример. Преобразуем отрицательное число −5, записанное в прямом коде, в дополнительный. Прямой код числа −5, взятого по модулю:

101 

Инвертируем все разряды числа, получая таким образом обратный код:

010

Добавим к результату 1 и допишем знаковый единичный разряд

1011

Для обратного преобразования используется тот же алгоритм. А именно:

1011

Инвертируем все разряды числа, получая таким образом обратный код:

100

Добавим к результату 1 и проверим, сложив с дополнительным кодом

 0101 + 1011 = 10000, пятый разряд выбрасывается.

[править] Дополнительный код для десятичных чисел

Тот же принцип можно использовать и в компьютерном представлении десятичных чисел: для каждого разряда цифра X заменяется на 9−X, и к получившемуся числу добавляется 1. Например, при использовании четырёхзначных чисел −0081 заменяется на 9919 (9919+0081=0000, пятый разряд выбрасывается).

[править] Реализация алгоритма преобразования в обратный код

[править] Pascal

if a<0
  then a:=(not a) or 128;

[править] C/C++

if (a < 0)
  a = (~a)|128;

[править] Преимущества и недостатки

[править] Преимущества

  • Один и тот же регистр может хранить как n-битовое положительное число, так и (n−1)-битовое число со знаком, с общими для обоих форматов операциями сложения, вычитания и левого сдвига.
  • Более удобная упаковка чисел в битовые поля.
  • Отсутствие числа «минус ноль».

[править] Недостатки

[править] Пример программного преобразования

Если происходит чтение данных из файла или области памяти, где они хранятся в двоичном дополнительном коде (например, файл WAVE), может оказаться необходимым преобразовать байты. Если данные хранятся в 8 битах, необходимо, чтобы значения 128-255 были отрицательными.

[править] C# .NET / C style

byte b1 = 254; //11111110 (бинарное)
byte b2 = 121; //01111001 (бинарное)
int c = (int)Math.Pow(2,(sizeof(byte)*8)-1);  //2 возводится в степень 7. Результат: 10000000 (бинарное)
int b1Conversion=(c ^ b1) - c;  //Результат: -2. А фактически, двоичный дополнительный код.
int b2Conversion=(c ^ b2) - c;  //Результат остается 121, потому что знаковый разряд - нуль.

[править] См. также