Дополнительный урок
- 1 year ago
- 0
- 0
Дополнительный код ( англ. "two’s complement" , иногда "twos-complement" ) — наиболее распространённый способ представления отрицательных целых чисел в компьютерах . Он позволяет заменить операцию вычитания на операцию сложения и сделать операции сложения и вычитания одинаковыми для знаковых и беззнаковых чисел, что упрощает архитектуру ЭВМ . В англоязычной литературе « обратный код » называют «дополнением единиц» ( англ. "ones' complement" ), а «дополнительный код» называют «дополнением двойки» ( англ. "two’s complement" ).
Дополнительный код для отрицательного числа можно получить инвертированием его двоичного модуля и прибавлением к инверсии единицы, либо вычитанием числа из нуля.
Дополнительный код двоичного числа определяется как величина, полученная вычитанием числа из наибольшей степени двух (из
для
-битного второго дополнения).
При записи числа в дополнительном коде старший разряд является знаковым. Если значение старшего разряда равно 0, то это значит, что в остальных разрядах записано положительное двоичное число , совпадающее с прямым кодом .
Двоичное 8-разрядное число со знаком в дополнительном коде может представлять любое целое в диапазоне от −128 до +127. Если старший разряд равен нулю, то наибольшее целое число, которое может быть записано в оставшихся 7 разрядах, равно .
Примеры:
Десятичное
представление |
Двоичное представление (8 бит), код: | ||
---|---|---|---|
прямой | обратный | дополнительный | |
127 |
0111 1111
|
0111 1111
|
0111 1111
|
1 |
0000 0001
|
0000 0001
|
0000 0001
|
0 |
0000 0000
|
0000 0000
|
0000 0000
|
−0 |
1000 0000
|
1111 1111
|
— |
−1 |
1000 0001
|
1111 1110
|
1111 1111
|
−2 |
1000 0010
|
1111 1101
|
1111 1110
|
−3 |
1000 0011
|
1111 1100
|
1111 1101
|
−4 |
1000 0100
|
1111 1011
|
1111 1100
|
−5 |
1000 0101
|
1111 1010
|
1111 1011
|
−6 |
1000 0110
|
1111 1001
|
1111 1010
|
−7 |
1000 0111
|
1111 1000
|
1111 1001
|
−8 |
1000 1000
|
1111 0111
|
1111 1000
|
−9 |
1000 1001
|
1111 0110
|
1111 0111
|
−10 |
1000 1010
|
1111 0101
|
1111 0110
|
−11 |
1000 1011
|
1111 0100
|
1111 0101
|
−127 |
1111 1111
|
1000 0000
|
1000 0001
|
−128 | — | — |
1000 0000
|
Тот же принцип можно использовать и в компьютерном представлении любой системы счисления , например, для десятичных чисел .
Изменение значений текущих разрядов числа не производится, но дописывается знаковый старший разряд, значение которого равно 0. Например число [+12'345] будет иметь следующее представление - [012'345]
Дописываем знаковый старший разряд, равный большей цифре данной системы счисления , в нашем случае - это 9, а также изменяем остальные разряды по определённому правилу; пусть значение цифры каждого разряда будет представлено переменной , кроме знакового, тогда представим следующий алгоритм действий:
Идея представления десятичного (как и любого другого) числа в дополнительном коде, идентична правилам для двоичной системы счисления и может использоваться в гипотетическом процессоре:
Привычное
представление |
Прямой
код |
Первое
дополнение |
Второе
дополнение |
---|---|---|---|
... | ... | ... | ... |
+13 | 0'0013 | 0'0013 | 0'0013 |
+12 | 0'0012 | 0'0012 | 0'0012 |
+11 | 0'0011 | 0'0011 | 0'0011 |
+10 | 0'0010 | 0'0010 | 0'0010 |
+9 | 0'0009 | 0'0009 | 0'0009 |
+8 | 0'0008 | 0'0008 | 0'0008 |
... | ... | ... | ... |
+2 | 0'0002 | 0'0002 | 0'0002 |
+1 | 0'0001 | 0'0001 | 0'0001 |
+0 | 0'0000 | 0'0000 | 0'0000 |
-0 | 9'0000 | 9'9999 | 0'0000 |
-1 | 9'0001 | 9'9998 | 9'9999 |
-2 | 9'0002 | 9'9997 | 9'9998 |
-3 | 9'0003 | 9'9996 | 9'9997 |
-4 | 9'0004 | 9'9995 | 9'9996 |
... | ... | ... | ... |
-9 | 9'0009 | 9'9990 | 9'9991 |
-10 | 9'0010 | 9'9989 | 9'9990 |
-11 | 9'0011 | 9'9988 | 9'9989 |
-12 | 9'0012 | 9'9987 | 9'9988 |
-13 | 9'0013 | 9'9986 | 9'9987 |
Оба числа представляются в дополнительном коде. Дополнительный код обоих чисел имеет одинаковое количество разрядов. В данном представлении числа складываются.
Знаки разные: Если в процессе сложения образуется выходящий за пределы первоначальных чисел разряд, то он опускается. Результирующее значение считается положительным , где прямой и дополнительный коды являются идентичными. Иначе — отрицательным в виде дополнительного кода .
Например:
Знаки одинаковые:
Например:
Преобразование числа из прямого кода в дополнительный осуществляется по следующему алгоритму.
Для примера преобразуем отрицательное число , записанное в прямом коде, в дополнительный код.
Прямой код отрицательного числа
:
1000 0101
1111 1010
1111 1011
Для преобразования отрицательного числа , записанного в дополнительном коде, в положительное число , записанное в прямом коде, используется похожий алгоритм:
0000 0100
0000 0101
И проверим, сложив получившееся записи
и
:
0000 0101 + 1111 1011 = 0000 0000
(пятый и старше разряды выбрасываются)
В системе p -адических чисел изменение знака числа осуществляется преобразованием числа в его дополнительный код. Например, если используется 5-ричная система счисления, то число, противоположное 0001 5 (1 10 ), равно 4444 5 (−1 10 ).
function TwosComplAbs(a: integer): integer;
begin
if (a < 0) then TwosComplAbs := (not a) + 1
else TwosComplAbs := a;
end;
int twos_compl_abs(int a) {
if (a < 0) a = (~a) + 1;
return a;
}
С помощью следующей формулы можно вычислить модуль числа без ветвления :
где:
— Операция
исключающего "или"
;
—
Арифметический сдвиг
вправо;
— Количество двоичных разрядов
Следующий код на языке Си вычисляет модуль по этой формуле:
int32_t fastabs32(int32_t num)
{
int32_t mask = (num >> 31);
return ((num ^ mask) - mask);
}
Если происходит чтение данных из файла или области памяти, где они хранятся в двоичном дополнительном коде (например, WAV файл ), может оказаться необходимым преобразовать байты. Если данные хранятся в 8 битах, необходимо, чтобы значения 128-255 были отрицательными.
byte b1 = 254; //11111110 (бинарное)
byte b2 = 121; //01111001 (бинарное)
byte c = 1<<(sizeof(byte)*8-1); //2 возводится в степень 7. Результат: 10000000 (бинарное)
byte b1Conversion=(c ^ b1) - c; //Результат: -2. А фактически, двоичный дополнительный код.
byte b2Conversion=(c ^ b2) - c; //Результат остаётся 121, потому что знаковый разряд - ноль.
Расширение знака ( англ. sign extension ) — операция над двоичным числом, которая позволяет увеличить разрядность числа с сохранением знака и значения. Выполняется добавлением цифр со стороны старшего значащего разряда. Если число положительное (старший разряд равен 0), то добавляются нули, если отрицательное (старший разряд равен 1) — единицы.
Примечание : Добавленные цифры подчёркнуты
Десятичное число |
Двоичное число
(8 разрядов) |
Двоичное число
(16 разрядов) |
---|---|---|
10 |
0000 1010
|
0000 0000
0000 1010
|
−15 |
1111 0001
|
1111 1111
1111 0001
|