区分2的补码负数和相应的正数

4
我将举例说明。十进制数5的4位二进制表示为0101。因此,十进制数-5在2的补码中表示为1011。然而,1011也是十进制数11的二进制表示。怎样区分这两个值?
如果解决方案是限制4位二进制数仅表示-8到+7,那么如何检测溢出?当我将二进制7加上二进制7时,得到1110,它是十进制数13(溢出),但也是2的补码中的二进制-2。如何检测二进制7 + 7是溢出,而不是-2?
我知道计算机通常使用2的补码来表示负数。我想知道在这种情况下如何处理这个问题。

有一个溢出位 - Nico Schertler
2个回答

2
没有办法区分具有相同表示的正数和负数。我曾经编写了一些程序,利用这种模糊性来完成工作。如你所说,通常的做法是将二进制数字的最高有效位(MSB)为1的标识为负数,最高有效位为0的标识为正数。对于四位二进制数,范围为-8到+7。
此外,CPU检测溢出的一种方法是比较进入MSB和离开MSB的进位位。如果这些位相同 - 都是零或都是一 - 则没有溢出。如果这些位不同 - 一个是零,另一个是一 - 则加法中发生了溢出。
在你的例子中,7加7或0111 + 0111,请注意当你将“111”加到“111”时(省略MSBs的值),你得到“1110”,因此结果为“110”,带有一个“1”进位到MSB。然后当你加上MSBs和进位时,你会看到“0 + 0 + 1”,它是“1”,没有从MSB流出的进位。因此进位输入为“1”,进位输出为“0”,因此发生了溢出。
许多CPU检测这些情况。在加法之后,一个状态位将是进位到MSB的进位位,另一个状态位将是离开MSB的进位位。如果这些位不同,则会引发溢出条件标志。

2

无法仅通过查看位序列将不同的含义赋予相同的位序列。无法区分字节11111111是表示有符号整数-1还是无符号整数255,就像无法区分字节00100001是表示数字33还是字符'A'一样。这些都是相同基础数据的不同解释。在现实世界中处理数据的方式是类型的概念,在几乎所有高级语言中都以某种方式支持。类型是允许选择一种解释而不是其他解释的东西。在许多较新和更高级的语言中,甚至没有简单的方法以其他方式解释相同的数据(字节);在一些较低级别的语言中(如C或C ++),如果你有充分的理由这样做,你实际上可以这样做。例如,你可以将8字节整数类型的数字5217737203189443684与十六进制表示为0x48 69 20 57 6F 72 6C 64的字符序列"Hi World"重新解释。在一些情况下,这样的技巧提供了好处,但在大多数情况下,这不是你应该做的事情(这就是为什么在许多语言中你不能轻松地这样做的原因)。
所以回到你的例子,许多语言有不同类型的“有符号整数”和“无符号整数”,这就允许区分这些情况。至于溢出,2的补码的一个好处是,在位级别上,对于“无符号整数”和“带符号2的补码整数”,加法和减法的逻辑实际上是相同的。因此,在硬件级别上,只需要检测溢出,设置相应的标志(溢出标志进位标志),然后将其解释留给用户。是-127 + -127还是129 + 129?硬件不关心。是-1 + 2还是255 + 2?同样,硬件不关心。它只设置标志,让您(或编译器)根据(逻辑上)分配的类型进行解释。
P.S. 关于溢出和进位标志的一些细节可在这里找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接