此文,关于上一篇博文做一个补充,关于补码的大小比较与算术溢出的判断方法。
造轮子:补码实现与若干分析
新开的CSDN博客,博文更新还要各种审核,于是不如新开一篇。
大小比较
补码的大小比较基本就是两步走,先比较符号位,同号再进一步比较。
// if a > b then return 1
// if a < b then return ~0
// if a == b then return 0
word compare(word a, word b){
if(a >> 31 > b >> 31) return ~0; // b >= 0 > a
if(a >> 31 < b >> 31) return 1; // a >= 0 > b
if(a < b) return ~0;
if(a > b) return 1;
return 0; // a == b
}
太简单了就不详细讲了,需要注意的是 ~0
是 -1 的一种简写(仅补码有效)
运算溢出分析
目前只想到了针对加减法比较好的溢出判断。
先讨论加法,因为减法可以转换为加法。
- 设两码 a=0,b∈[0,2n) (a,b 中有至少一个为 0)、
则有a+b=b
由于 b 本身合法,所以不可能溢出。 - 设两码 a∈(0,2n−1),b∈(0,2n−1) (a,b所表示的均为正数)
a+b∈(0,2n−1)
2n−2>2n−1−1,(n>2)
看上去是可能溢出的,而且乍一看似乎没有办法直接处理。
然而,在数学上,非负数a, b应均不超过它们之和 a + b。
如果这个条件不成立,则视为运算溢出。
基于上面的情况(a, b均表示正数),下面证明
若 a+b≥2n−1 ,则 mtoa(a+b)<mtoa(a)且mtoa(a+b)<mtoa(b)
证:
不妨设