在网上看了很多有符号定点小数运算溢出判别的文章,大多讲的都是那三个方法举几个例子,但并没有讲为什么是那三个公式,以及意义,所以我想记录一下自己的想法。
因为溢出只有正+正=负,负+负=正,所以下文不考虑正+负,负+正的情况
此处 溢出分为正溢 和 负溢
正溢就是两个正数相加超出界限了,结果是负数——补码表示,符号位变化——0+0 = 1
负溢就是两个负数相加超出界限了,结果是正数——补码表示,符号位变化——1+1 = 0
方法一:
单符号位
已知:两操作数符号相同,运算结果的符号与原操作数符号不同,就表示溢出
设:操作数A的符号位As,操作数B的符号为Bs,运算结果的符号为Ss
默认:表示正数的符号位;,,表示负数的符号位
若V=0,无溢出;若V=1,有溢出
左边:代表 负数A + 负数B = 正数S 这种溢出情况,As=1,Bs=1,Ss=0,与运算结果为1
右边:代表 正数A + 正数B = 负数S 这种溢出情况,As=0,Bs=0,Ss=1,与运算结果为1
若满足 负+负=正 或 正+正=负 就是溢出了,‘或’ 翻译为‘+’
这个公式就是对这两种情况的综合概况
方法二:
单符号位,根据进位情况来判断
两个定义:设符号位进位为Cs,最高位进位为C1,⊕表示异或。
公式: V = Cs⊕C1
一般就会说,这两个不一样就会造成正溢和负溢,那为什么呢?
简单来讲,两个正数相加,若符号位不产生进位(Cs=0),最高位产生进位(C1=1),这个进位的1就给符号位了,正+正,符号位本来为0,收到了最高位进位的1后就从0变成1了,发生正溢。
两负数相加,符号位产生进位(Cs=1),最高位不产生进位(C1=0),最高位就相当于撤出战斗了,目光可以只放在符号位上,那符号位此时在干嘛呢? 1+1=10,进位1,这个进位的1由于位数有限,1被抛弃),只剩下一个0代表正数,那不就是1+1 = 0,这符合负溢定义
符号位进位Cs | 最高位进位C1 | |
无溢出 | 0 | 0 |
正溢 | 0 | 1 |
负溢 | 1 | 0 |
无溢出 | 1 | 1 |
举个小栗子:
那么Cs,C1同时为0或1时会怎么样呢?(只考虑0+0,1+1)
- 同时为0,最高位先撤出战斗,只看符号位,0+0=0,毫无疑问结果是一个正数,未溢出;
- 同时为1,最高位进位1,然后看符号位,1+1(前两个是符号位)+1(进位来的)=11(黄色被抛弃,蓝色被保留),符号位还是1,负+负=负,没有溢出
例:Cs=1,C1=1,它的结果确实没有溢出,是不是很神奇
综上,C1和C2不一样时为溢出,而处理不同的电路不就是异或⊕吗?
所以V = C1⊕C2
方法三:
双符号位
把符号位由以前的一位延长至两位,个人认为这个的判断和方法二其实道理一样
正数符号为00,负数符号为11,那么为什么01表示正溢,10表示负溢呢?
可以想一下什么时候会出现01,只有00+00,最高位进位为1时才有可能(没忘记上面说的最高位进位C1吧),那不就是正+正=负吗
同理,10不也是11+11=110(黄色为舍弃),最高位进位为0时才有可能,那不就是负+负=正吗;若C1=1,那结果就是111,结果是个负数,没有溢出
综上,设两符号位为S1,S2,只有S1,S2不同时才会有溢出,处理不同用异或⊕
所以V = S1⊕S2