Обнаружение отрицательных двоичных

сегодня в классе мой учитель вычислений объяснял нам (или пытался объяснить), как написать отрицательное двоичное число, используя дополнение Two. Мой вопрос таков:--1-->

как конечный пользователь определяет разницу между 11101100 быть 236 и -20? Я знаю, что вы всегда можете проверить самый значительный бит, но всегда ли это 100% точно? Является ли это соглашением отрицательных двоичных чисел, чтобы самый значительный бит указывал на знак?

сторону Примечание:
Почему мы изучаем двоичное вычитание, когда мы можем просто сделать:

преобразовать двоичный в денарный - > вычесть денарный - > преобразовать в двоичный

4 ответов


Вопрос 1:

" это соглашение отрицательных двоичных чисел, чтобы самый значительный бит указывал знак?"

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

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

b2b1b0 = 22b2 + 21b1 + 20b0 = 4b2 + 2b1 + b0

1112 = 710
1102 = 610
1012 = 510
1002 = 410
0112 = 310
0102 = 210
0012 = 110
0002 = 010

два-дополнение
Есть несколько способов взглянуть на 2S-дополнение, я думаю, что ответ очевиден во всех из них. Один из способов получить эту систему взять верхнюю половину чисел без знака (которые все имеют высокий бит) и переместить их ниже нуля:

0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -110
1102 = -210
1012 = -310
1002 = -410

вы можете ясно видеть, что старший бит указывает на знак. Опять же, 0 занимает одно из 4 положительных представлений, что приводит к тому, что диапазон не является симметричным: [3, -4] (хотя иногда наиболее отрицательное значение считается особенным, делая использовать диапазон симметричный). Эквивалентно, мы можем переинтерпретировать бит высшего порядка как отрицательное число:

b2b1b0 = -(22) b2 + 21b1 + 20b0 = -4 b2 + 2b1 + б0

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

из этого определения мы можем вывести третью интерпретацию: общеизвестное правило, что -a = ~a + 1 (где - означает арифметическое отрицание, ~ означает побитовое дополнение, и мы игнорируем переполнение):

a + ~a = - 4b2 + 2b1 + b0 + -4 (~b2) + 2 (~b1) + ~b0
a + ~a = -4 (b2+~b2) + 2 (b1+~b1) + (b0+~b0)
a + ~a = -4(1) + 2(1) + (1)
a + ~a = -1
a = - (~a + 1)
- a = ~a + 1

здесь мы видим, что отрицание переворачивает высокой скорости, поэтому он указывает на знак числа. Обратите внимание, что это не строго true, так как добавление с одним может перевернуть высокий бит назад, если все остальные биты установлены. Однако это относится только к 0 и самому отрицательному числу (-410, или 1002, в этом случае), оба из которых остаются неизменными при отрицании.

преимущество в использовании 2S-complement заключается в том, что то же самое аппаратное обеспечение может использоваться для подписанного и неподписанного добавления. Это хорошее свойство не относится к другим отрицательным двоичным представлениям, которые использовались в прошлом, некоторые из которых я кратко коснусь. Из-за этого современные процессоры почти всегда используют это представление для целочисленной арифметики (я не знаю каких-либо недавних коммерческих контрпримеров, но они могут быть там). Вот почему вы узнаете об этом (в отличие от Convert binary to denary -> subtract denary -> reconvert into binary): чтобы понять, как операции работают на уровне ворот Алю.

один-дополнить
1S-дополнение тесно связано с 2S-дополнением. Отрицание выполняется путем инвертирования только битов (без добавления 1). Ведущий бит по-прежнему указывает знак, но существуют различные представления для положительного и отрицательного нуля. Я никогда лично не сталкивался с реальным использованием 1S-дополнения, но это представляет исторический интерес.

b2b1b0 = - 3b2 + 2b1 + b0

0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -010
1102 = -110
1012 = -210
1002 = -310

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

b2b1b0 = (-1)b2(2b1 + b0)

0 11 2 = + 3 10
0 10 2 = + 2 10
0 01 2 = + 1 10
0 00 2 = + 0 10
1 00 2 = - 0 10
1 01 2 = - 1 10
1 10 2 = - 2 10
1 11 2 = - 3 10

избыток-n
Excess-n действительно больше похоже на семейство систем. Все значения сдвигаются вверх на n (известный как смещение), а затем представлен как в случае без знака. Ведущий бит мая укажите знак, если выбрано правое смещение, хотя и с другой полярностью, чем вышеупомянутые системы (и 0 может быть сгруппирован либо с негативами, либо с позитивами). Это все еще используется в показатель числа с плавающей запятой IEEE. При n = 3 высокий бит указывает на знак, а 0 группируется с отрицательными числами:

b2b1b0 = 4b2 + 2b1 + b0 - n

1112 = 410
1102 = 310
1012 = 210
1002 = 110
0112 = 010
0102 = -110
0012 = -210
0002 = -310

другие
Есть еще другие, более эзотерические целочисленные представления, такие как balanced-ternary, base-negative-2 или (возможно) двоично - десятичный код (или BCD для краткости). Причина, по которой я говорю, что BCD спорен, заключается в том, что современные процессоры часто все еще поддерживают его (Хотя это не то, как числа представлены внутри), и многие калькуляторы использовали его. В этих системах ведущий бит (или trit, или цифра base-n) может указывать или не указывать знак (или может указывать его в некоторых случаях, но не в других).

Вопрос 2:

" как конечный пользователь определяет разницу между 11101100 быть 236 и -20?"

в общем, нет способа узнать, действительно ли число, хранящееся в регистре или памяти, должно быть 2S-дополнением или без знака, как указывали другие. Вы по существу должны отслеживать, что с ним сделано, чтобы определить это.

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

например, могут быть отдельные инструкции "загрузить немедленно" и "загрузить подписанный немедленно", которые копируют значение немедленного значения в больший регистр, второй делает знак-расширение и Первый нет. Инструкции "ветви" часто имеют подписанный немедленный, чтобы указать размер прыжка (так что как вперед, так и назад ветви могут использовать один инструкция.) Могут быть разные инструкции "добавить немедленное" и "добавить неподписанное немедленное", которые устанавливают флаги переполнения соответствующим образом для типа добавления.

расширение знака
Расширение знака означает копирование высокого бита для сохранения значения номера дополнения 2s. Это приведет к неправильным результатам для половины неподписанных чисел.

расширение знака не выполняется:

1002 = 000001002
Без подписи: 410 = 410
Подпись: -410 = 410

расширение знака, выполненного:

1002 = 111111002
Подпись: -410 = -410
Без подписи: 410 = 25210

0012 = 000000012
Подписано и без подписи: 110 = 110

переполнения
Добавление или вычитание двух чисел может дать результат, который слишком велик (в абсолютном смысле), чтобы быть правильно представлен. Добавление тех же двух двоичных последовательностей может вызвать переполнение для подписанных чисел, но не без знака (или наоборот).

Signed переполняет, но unsigned не делает:

0112 + 0112 = 1102
Подписано: 310+310 = -210
Без подписи: 310+310 = 610

неподписанный переполняет, но подписанный не делает:

1112 + 0102 = 0012
Без подписи: 710 + 210 = 110
Подпись: -110 + 210 = 110


  1. в нотации дополнения two, самый высокий бит всегда указывает знак. Однако вы должны знать ширину поля, а также знать, используется ли нотация дополнения two. Например, если 11101100-это 32-разрядное число, то наиболее значимый бит равен 0, т. е. +236. Если это без подписи 8-разрядное целое число, то есть +236, потому что беззнаковые числа не используют нотацию дополнения two (только знаковые числа делать.)

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


как конечный пользователь определяет разницу между 11101100 236 и -20?

пользователь не может определить его только по битовому шаблону. Некоторый контекст должен сказать, является ли этот байт подписанным или неподписанным. В большинстве языков программирования этот контекст отслеживается путем отслеживания типов. Таким образом, в C или C++ у вас есть signed char и unsigned char. (Старая добрая char может быть любой).

есть причина, по которой двоичное вычитание работает что это (как и некоторые другие операции) происходит точно так же с битовым шаблоном, даже если вы получили тип "неправильно". Один из способов думать об этом-это (для этих операций) вы делаете арифметическое по модулю 256, и в этом модуле 236 и -20 фактически два имени для одного и того же числа.


короткий ответ: это зависит от того, как вы используете его. Почти все современные компиляторы представляют их целочисленные значения как комплимент. Это съезд. Если вы пишете свой код в сборке, вам нужно обратить более пристальное внимание на то, что находится в памяти или в регистре, но на языках более высокого уровня тип данных значения говорит вам. Если тип подписан, то MSB является битом знака, иначе это не так. Тип данных также сообщает вам, сколько битов находится в значении, поэтому вы будете возможность определить, какой бит является MSB. Например, int8_t всегда 8 бит и подписан, тогда как uint8_t всегда 8 бит, но без знака. Пока вы знаете, как определить тип данных, вы точно знаете, как интерпретировать значение в памяти, когда вы видите его представленным в двоичном формате.