Дополнительный код (представление числа)
Материал из Википедии — свободной энциклопедии
Дополнительный код (англ. 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
[править] Преобразование дополнительного кода
Преобразование числа из прямого кода в дополнительный осуществляется по следующему алгоритму.
- Если число, записанное в прямом коде, положительное, то к нему дописывается старший (знаковый) разряд, равный 0, и на этом преобразование заканчивается;
- Если число, записанное в прямом коде, отрицательное, то все разряды числа инвертируются, а к результату прибавляется 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, потому что знаковый разряд - нуль.

