0b1000 1111 + 0b1001 1000 = 0b1 0010 0111
Включая перенос как n + 1-й бит результата в бессмысленно для дополнения 2 с.То, что вы можете сделать, это либо придерживаться оригинального размера
0b1000 1111 + 0b1001 1000 = 0b0010 0111 // неверный
, либо расширить операнды до n + 1 бит иполучить результат n + 1 бит.
0b1 1000 1111 + 0b1 1001 1000 = 0b1 0010 0111 // действительный
Причина в том, что дополнение 2s работает путем добавления 2^ n к отрицательным целым числам, чтобы сделать их положительными.(для кодирования a <0 = - | a | используйте 2 ^ n + a или 2 ^ n - | a |, то есть дополнение к 2 ^ n из | a |, отсюда и название дополнения 2s). </p>
Это здорово, так как закодированное значение равно (2 ^ n) + a, если a <0, или a, если a≥0, и если вы игнорируете 2 ^ n, вы можете добавить целое число со знаком, не беспокоясь о знакеоперанды.Но вы <em>должны игнорировать выполнение (за исключением того, что касается действительности).
Чтобы получить точные правила действительности, вы должны рассмотреть различные ситуации:
1 / A, B> = 0
Результат действителен, если MSB = 0 ⇒ c_n-1 = 0 (и мы всегда имеем c_n = 0)
2 / A, B <0 </p>
Результат действителен, если MSB = 1 ⇒ c_n-1 = 1 (и мы всегда имеемc_n = 1)
3 / A> = 0, B <0 </p>
Результат не может быть слишком положительным или слишком отрицательным ивсегда в силе.И у нас всегда есть c_n = c_n-1
. Мы видим, что глобальное правило, которое указывает, является ли результат действительным, состоит в том, что c_n == c_n-1 (или c_n ⊕ c_n-1 указывает на переполнение).
Есть много других эквивалентных правил.Например:
результат действителен, если (знак (A)! = Знак (B)) или ((знак (A) == знак (B)) и (знак (A) == знак (A + B))
, которое можно выразить в C как
((a^b) | (a^~(a+b)))&(1<< sizeof (int) -1)