6

当使用二进制补码执行按位减法时,如何知道何时应该忽略溢出?我读过的几个网站说溢出被简单地忽略了,但这并不总是有效 - 溢出对于诸如 之类的问题是必要的-35 - 37,因为需要一个额外的数字来表达-72.

编辑:这是一个例子,使用上面的等式。

35到 binary -> 100011,找到二进制补码使其为负:011101

37到 binary -> 100101,找到二进制补码使其为负:011011

执行上述项的加法(二进制等价于-35 - 37):

011101
011011
------
111000

取二进制补码转换回正数:001000

以上是许多网站(包括学术网站)所说的答案,因为您忽略了溢出。然而,这显然是不正确的。

4

1 回答 1

5

当结果无法以目标数据类型表示时,就会发生溢出。值 -72 可以用 char 表示,它是一个有符号的 8 位量......在您的示例中没有溢出。也许您正在考虑borrow进行按位减法...当您从'1'a 中减去 a 时,'0'您需要borrow从下一个高阶位位置中减去。做减法时不能忽略借位。

-35 decimal is   11011101 in two's complement 8-bit
+37 decimal is   00100101 in two's complement 8-bit

从最低有效位到最高有效位从右到左,您可以从 -35 中的每个位中减去 +37 中的每个位,直到到达第 5 位(从右侧的第 0 位开始计数)。在第 5 位,您需要从中减去'1''0'因此您需要从 -35 中的第 6 位(下一个高阶位)借用,这恰好是'1'借用之前的。结果看起来像这样

-35 decimal is   11011101 in two's complement 8-bit
+37 decimal is   00100101 in two's complement 8-bit
                 --------
-72 decimal is   10111000 in two's complement 8-bit

结果是否定的,并且您在 8 位二进制补码中的结果设置了高位(第 7 位)......这是负数,因此没有溢出。

更新:我想我知道混乱在哪里,并且我声称这里的答案加减二进制补码是错误的,当它说你可以时discard the carry (indicates overflow)。在那个答案中,他们通过使用二进制补码将第二个操作数转换为负数然后加法来进行减法。这很好 - 但在这种情况下进位并不代表溢出。如果您在 N 位(编号 0 到 N-1)中添加两个正数,并且您考虑这个无符号算术range 0 to (2^N)-1并且您得到位位置 N-1 的进位,那么您有溢出 - 两个正数之和(解释为无符号最大可表示的正数范围)不应产生最高位(位 N-1)的进位。因此,当添加两个正数时,您可以通过说来识别溢出

  1. 当您将它们解释为无符号和
  2. 当解释为有符号(二进制补码)时,位 N-1 中的结果必须为零

但是请注意,处理器不区分有符号和无符号加/减...它们设置溢出标志以指示如果您将数据解释为有符号,则无法表示结果(错误)。

这是进位和溢出标志的非常详细的解释。那篇文章的要点是

  • unsigned算术中,观察进位标志以检测错误。
  • unsigned算术中,溢出标志告诉你什么有趣的东西。

  • signed算术中,观察溢出标志以检测错误。

  • signed算术中,进位标志告诉你什么有趣的东西。

这与维基百科中算术溢出的定义一致,该定义说

大多数计算机区分两种溢出条件。当加法或减法的结果(将操作数和结果视为无符号数)不适合结果时,就会发生进位。因此,在添加或减去被解释为无符号值的数字后检查进位标志很有用。当结果没有从操作数的符号中预测的符号时(例如,两个正数相加时的负结果),就会发生溢出。因此,在以二进制补码形式表示的数字(即它们被认为是有符号数字)相加或相减后检查溢出标志是很有用的。

于 2013-02-05T23:40:09.757 回答