我详细说明了以下例子。十进制5的4位二进制表示为0101.因此,十进制-5在2的补码中表示为1011.但是,1011也是十进制11的二进制表示。如何区分这两个?
如果解决方案是将4位二进制数限制为仅表示-8到+7,如何检测到溢出?当我将二进制7添加到二进制7时,我得到1110,即十进制13(溢出),但也是2的补码中的二进制-2。如何检测到二进制7 + 7是溢出,而不是-2?
据我所知,计算机通常使用2的补码来表示负数。我想知道在这种情况下如何处理这个问题。
答案 0 :(得分:2)
仅仅查看这些位就不可能为相同的位序列分配不同的含义。无法区分字节11111111
表示带符号-1
还是无符号255
,就像无法区分字节00100001
是否代表数字{{1}一样}或一个字符33
。这些是相同底层数据的不同解释。它在现实世界中的处理方式是类型的概念,几乎在任何高级语言中都以某种方式支持它。类型是允许选择一种解释而不是其他解释的东西。在许多较新的和更高级别的语言中,甚至没有简单的方法以某种其他方式解释相同的数据(字节);在一些较低级别的语言(如C或C ++)中,如果你有充分的理由,你实际上可以这样做。例如,您可以使用一个8字节整数类型的'A'
,其十六进制表示为5217737203189443684
,并将其重新解释为字符序列0x48 69 20 57 6F 72 6C 64
。在某些情况下,这些技巧会带来好处,但在大多数情况下,这不是你应该做的事情(这就是为什么你不能在很多语言中轻松完成的原因)。
回到你的例子,许多语言对于“有符号整数”和“无符号整数”有不同的类型,这就是允许区分这些情况的原因。并且溢出一个2的补码的一个很好的属性是在位级别上加法和减法的逻辑实际上对于“无符号整数”和“有符号2的补码整数”是相同的。因此,在硬件级别上,所需要的只是检测溢出,设置相应的标志(overflow flag和carry flag),然后将这些标志的解释留给用户。是"Hi World"
还是-127 + -127
?硬件不关心。那是129 + 129
还是-1 + 2
?硬件再也不关心了。它只是设置标志,让你(或编译器)根据(逻辑上)分配的类型解释它。
P.S。有关溢出和进位标志的一些详细信息可用here
答案 1 :(得分:1)
无法用相同的表示来区分正数和负数。我做了一些程序,我用这种模糊性来完成工作。正如你所说,通常的做法是说一个二进制数,其最高有效位(MSB)为1
为负数,其最高有效位为0
为正数。对于四位,给出范围-8到+7。
此外,CPU检测溢出的一种方法是比较进入MSB的进位和从MSB出来的进位。如果这些位是相同的 - 零或两者都是 - 那么就没有溢出。如果这些位不同 - 一个为零而另一个为1 - 则在添加中存在溢出。
在7加7或0111 + 0111
的示例中,请注意,当您将111
添加到111
(遗漏MSB的值)时,您会得到{{1}结果是1110
,其中110
进位位进入MSB。然后,当您添加MSB和进位时,您会看到1
0+0+1
并且没有执行MSB。因此,结转为1
,结转为1
,因此存在溢出。
许多CPU检测到这些情况。在加法之后,一个状态位将是进入MSB的进位位,另一个状态位将是MSB的进位位。如果这些位不同,则会引发溢出条件标志。