2013-02-05 73 views
5

使用二进制补码执行按位相减时,如何知道何时应该忽略溢出?我读过的几个网站都表示,溢出只是被忽略,但这并不总是有效 - 对于像-35 - 37这样的问题,溢出是必需的,因为需要额外的数字来表示-72的答案。使用二进制补码进行按位相减的溢出

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

35二进制 - >100011,发现两个互补,使其负:011101

37二进制 - >100101,发现两个互补,使其负:011011

执行除上述条款(的-35 - 37二进制数):

011101 
011011 
------ 
111000 

采取补转换b ack to positive:001000

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

+1

显然,那些网站并没有描述如何按位计算'-32 - 37':-) –

+2

[This answer](http://stackoverflow.com/a/3878135/1672458)声明:以及关于[此学术网页]步骤4(http://courses.cs.vt.edu/~csonline/NumberSystems/Lessons/SubtractionWithTwosComplement/index.html)。 [这个PowerPoint演示(http://docs.google.com/viewer?url=http%3A%2F%2Fwww.cs.uiuc.edu%2Fclass%2Fsp08%2Fcs231%2Flectures%2F10-Subtraction.pdf)(谷歌浏览器链接)也显示在幻灯片9上。 – vaindil

+0

什么是按位减法?你的意思是减去2的补数?如果是这样的话,那么你的问题应该是,当2的补码加上宽度为N的负整数时(例如)是否溢出? – AraK

回答

5

当目标数据类型中无法表示结果时发生溢出。值-72可以用char来表示,这是一个有符号的8位数量......在您的示例中没有溢出。也许你正在考虑borrow,而按位相减......当你从'0'减去'1'你需要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位,您需要从'0'中减去'1',因此您需要借用-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位)......这是负的,所以没有溢出。

更新:我觉得我看到那里的混乱是的,我要求的是,这里Adding and subtracting two's complement答案是错误的,当它说,你可以discard the carry (indicates overflow)。在那个答案中,他们通过使用二进制补码将第二个操作数转换为负数然后进行相减来进行相减。这很好 - 但在这种情况下进位不代表溢出。如果在N位(编号为0到N-1)中添加两个正数,并且您考虑这个无符号算术range 0 to (2^N)-1,并且您得到位位置N-1的执行,那么您有溢出 - 两个正数的总和(解释为无符号数以最大化可表示正数的范围)不应生成最高位(第N-1位)的执行。因此,增加了两个正数时,你说

  1. 必有无进位的N-1,当你将其解释为无符号和
  2. 结果中位N-1必须为零解释时确定溢出作为符号(2的补数)

但是请注意,该处理器不签署和未加/减...他们设置的溢出标志,以表明如果你解释你的数据区分的签署然后结果库尔d不被表示(是错误的)。

这里是a very detailed explanation of carry and overflow flag。从这篇文章中得到的结论是这样的

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

  • signed算术,看溢出标志来检测错误。

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

这与definition of arithmetic overflow in Wikipedia它说

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

+0

最初的问题是由一个需要6位数的作业问题引起的,因此我的(刚刚添加的)例子被写入。如此多的网站(请参阅我的第一篇关于主文章的评论)都会说忽略溢出,但事实并非如此。 – vaindil

+1

好吧,这改变了......如果你限制在6位数字,那么你有一个代表-35和+37的问题,这两个都需要7位二进制补码来表示。在二进制补码中,6位数字的范围是-32到+31(100000二进制到011111二进制)。 – amdn

+0

正如我在留言中指出的那样,试图在比特深度中表示一个没有考虑符号位保留的有符号整数是不允许的,我认为*是这个问题的根本问题值呈现。所以我相信这个答案是准确的。 – WhozCraig