在网上看了很多有符号数运算溢出判别的文章,大多讲的都是那三个方法举几个例子,但并没有讲为什么是那三个公式,以及意义,所以我想记录一下自己的想法。
因为溢出只有正+正=负,负+负=正,所以下文不考虑正+负,负+正的情况
溢出分为正溢和下溢
正溢就是两个正数相加超出界限了,结果是负数——补码表示,符号位变化——0+0 = 1
下溢就是两个负数相加超出界限了,结果是正数——补码表示,符号位变化——1+1 = 0
方法一:
单符号位
这里我最不理解的就是公式为什么长这样,只能勉强有个解释,欢迎懂的小伙伴交流啊
公式长这样,听说左边和右边是两个情况的反应。
左边对应fa=0,fb=0,fs=1这种情况与运算结果为1
右边对应fa=1,fb=1,fs=0这种情况与运算结果为1
方法二:
单符号位,根据进位情况来判断
两个定义:设符号位进位为C1,最高位进位为C2,⊕表示异或。
公式: V = C1⊕C2
一般就会说,这两个不一样就会造成上溢和下溢,那为什么呢?
符号位进位C1 | 最高位进位C2 | |
无溢出 | 0 | 0 |
上溢 | 0 | 1 |
下溢 | 1 | 0 |
无溢出 | 1 | 1 |
先看上溢:
C1 = 0,符号位没有进位,那就是符号位0+0,也就是两个正数相加;
因为只有0+0,1+1才会导致溢出的可能,所以0+1,1+0这些符号位的加法就不用考虑了;而1+1会导致C1 = 1,不符合当前情况
C2 = 1,最高位进位1,符号位变成1了,结果是一个负数,那不就是0+0 = 1,这符合上溢定义
再看下溢:
C1 = 1,符号位有进位,那就是符号位1+1,也就是两个负数相加;
因为只有0+0,1+1才会导致溢出的可能,所以0+1,1+0这些符号位的加法就不用考虑了
C2 = 0,最高位无进位,符号位变成0了(符号位本来就在1+1=10,进位1,这个进位由于位数有限,1被抛弃),结果是一个正数,那不就是1+1 = 0,这符合下溢定义
举个小栗子
那么C1,C2同时为0或1时会怎么样呢?(只考虑0+0,1+1)
同时为0,毫无疑问结果是一个正数
同时为1,如下面,它确实结果没有溢出,是不是很神奇
综上,C1和C2不一样时为溢出,而处理不同的电路不就是异或⊕吗?
所以V = C1⊕C2
方法三:
双符号位
把符号位由以前的一位延长至两位,个人认为这个的判断和方法二其实道理一样
正数符号为00,负数符号为11,那么为什么01表示上溢,10表示下溢呢?
可以想一下什么时候会出现01,只有00+00,最高位进位为1时才有可能(没忘记上面说的最高位进位C2吧),那不就是正+正=负吗
同理,10不也是11+11=110(黄色为舍弃),最高位进位为0时才有可能,那不就是负+负=正吗;若C2=1,那结果就是111,结果是个负数,没有溢出
综上,设两符号位为S1,S2,只有S1,S2不同时才会有溢出,处理不同用异或⊕
所以V = S1⊕S2