Бинарная форма дополнения двоих - PullRequest
0 голосов
/ 17 марта 2009

В компиляторе TC ++ двоичное представление 5 равно (00000000000000101) . Я знаю, что отрицательные числа хранятся в виде дополнения 2, поэтому -5 в двоичном виде - (111111111111011) . Самый значимый бит (знаковый бит) равен 1, что говорит о том, что это отрицательное число.

Так как же компилятор узнает, что это -5 ? Если мы интерпретируем приведенное выше двоичное значение (111111111111011) как число без знака, оно получится совершенно другим?

Кроме того, почему 1 комплимент 5 -6 (1111111111111010) ?

Ответы [ 8 ]

8 голосов
/ 17 марта 2009

Компилятор не знает . Если вы разыгрываете -5 на unsigned int, вы получите 32763.

5 голосов
/ 17 марта 2009

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

Статья в Википедии на эту тему объясняет, как работает дополнение к двум .

3 голосов
/ 17 марта 2009

Процессор реализует инструкции со знаком и без знака, которые по-разному работают с представлением двоичных чисел. Компилятор знает, какие из этих команд выдавать, основываясь на типе задействованных операндов (т. Е. int против unsigned int).

Компилятору не нужно знать, является ли число отрицательным или нет, он просто выдает правильные машинные или промежуточные языковые инструкции для соответствующих типов. Реализация этих инструкций процессором или средой выполнения обычно не сильно заботит, является ли число отрицательным или нет, так как арифметика дополнения двух такова, что она одинакова для положительных или отрицательных чисел (на самом деле, это главный Преимущество арифметики дополнения до двух). Что нужно знать, если число отрицательное, будет что-то вроде printf(), и, как отметил Эндрю Джаффе, установленный MSBit указывает на отрицательное число в дополнении к двум.

2 голосов
/ 03 декабря 2010

приведем пример: у нас есть два числа в двух байтах в двоичном виде: A = 10010111 B = 00100110 (обратите внимание, что машина не знает понятия подписанного или неподписанного на этом уровне)

теперь, когда вы говорите "добавить" эти два, что означает машина? он просто добавляет:

R = 10111101 (и бит переноса: 1)

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

1- беззнаковый случай: в c числа имеют тип "unsigned char", значения 151 и 38, а результат 189. Это тривиально.

2 - случай со знаком: мы, компилятор, интерпретируем числа в соответствии с их msb, и первое число равно -105, а второе - 38. Поэтому -105 + 38 = -67. Но -67 - это 10111101. Но это то, что мы уже имеем в результате (R)! Результат тот же, разница только в том, как его интерпретирует компилятор.

Вывод состоит в том, что независимо от того, как мы рассматриваем числа, машина выполняет одну и ту же операцию над числами. Но компилятор будет интерпретировать результаты в свою очередь.

Обратите внимание, что это не машина, которая знает концепцию дополнения 2 . он просто добавляет два числа, не заботясь о содержании. Компилятор затем просматривает бит знака и решает .

Когда дело доходит до вычитания, на этот раз операция уникальна: возьмите 2-е дополнение второго числа и добавьте два.

2 голосов
/ 17 марта 2009

Дополнительным дополнением kewl является то, что инструкции машинного языка Add и Subtract могут игнорировать все это и просто выполнять двоичную арифметику, и она просто работает ...

, т.е. -3 + 4

в дополнении Binary 2, составляет

   1111 1111 1111 1101   (-3)
+  0000 0000 0000 0100   ( 4)
   -------------------
   0000 0000 0000 0001   ( 1)
2 голосов
/ 17 марта 2009

Первый бит устанавливается только для отрицательных чисел (он называется знаковым битом)

Подробная информация доступна здесь

1 голос
/ 17 марта 2009

Если число объявлено как тип данных со знаком (а не как тип, приведенный к типу без знака), то компилятор будет знать, что, когда бит знака равен 1, это отрицательное число. Что касается того, почему дополнение 2 используется вместо дополнения 1, вы не хотите иметь возможность иметь значение -0, какое дополнение 1 позволит вам сделать, поэтому они изобрели дополнение 2, чтобы это исправить.

0 голосов
/ 17 марта 2009

Это именно тот самый важный бит - если вы знаете, что число подписано, то если MSB = 1, то компилятор (и среда выполнения!) Знает, что он интерпретируется как отрицательный. Вот почему с-подобные языки имеют как целые числа (положительные и отрицательные), так и целые числа без знака - в этом случае вы все интерпретируете их как положительные. Следовательно, байт со знаком идет от -128 до 127, а байт без знака от 0 до 255.

...