P60 整数运算

1.无符号数加法

非负整数x,y,满足0<=x,y<2ω,x和y都能表示为ω位的无符号整数。

x+y的范围是[0,2*2ω-2),这就有可能需要ω+1位来表示。

计算机在进行无符号数的加法时,用ω+1位来运算,实际结果是截断此运算结果ω位得到的,即丢弃最高位

可以分两种情况来看:

1)若x+y的范围仍然是[0,2ω),则此时最高位必定为0,所以丢弃最高位不影响其大小。

2)若x+y超过了2ω,此时最高位必定为1,丢弃最高相当于减去2ω。这就是溢出。

//无符号加法也可以视为一种模运算,加法结果=实际结果mod 2ω

例. x=9,y=12,x和y都可以表示为4位,[1001]和[1100],4位的表示范围为[0,16),而9+12=21,已经超过了4位的表示范围,需要五位来表示,即[10101],丢弃最高位1,得到[0101],表示的无符号数为5,与5=9+12-16一致,也与5=(9+12)mod16一致。

无符号数的加法规则:

x 无符号加 y = x + y,x+y<2ω

扫描二维码关注公众号,回复: 8744200 查看本文章

x 无符号加 y = x + y - 2ω,x+y>2ω

无符号数溢出的判断

设s = x 无符号加 y,已知x>=0,y>=0,若无溢出,则必有s>=x且s>=y

反之,若有s<x或s<y,则必定发生了溢出。

int uadd_ok(unsigned x,unsigned y){return x+y>=x;}

求无符号数的加法逆元(相反数)

-x=2ω-x,x>0 (x=0时,-x=0)

2.补码加法

整数x,y,满-2ω-1<=x,y<=2ω-1-1,x和y都能用ω位的补码表示。

由于补码的第一位是符号位,所以ω位的补码表示的范围是[-2ω-1,2ω-1-1]

和无符号数一样用截断的方法处理补码加法。

x + y = x + y - 2ω , 2ω-1 <= x + y

x + y = x + y , -2ω-1 <= x + y < 2ω-1

x + y = x + y + 2ω , x + y < -2ω-1

简而言之,正溢出减去2ω,负溢出加上2ω

检验补码加法是否溢出

当x>0,y>0,有s<0

当x<0,y<0,有s>0

上述两种情况发生溢出。

错误代码

int tadd_ok(int x,int y)
{
    int sum=x+y;
    return (sum-x==y)&&(sum-y==x);
}

上述代码永远返回true

因为即使发生了溢出,但运算是可逆的,sum-x==y恒成立。

补码的加法逆元

当x=-2ω-1,-x=-2ω-1

当x>-2ω,-x=-x

当x为表示范围里的最小值即-2ω-1,-2ω-1+(-2ω-1)= -2ω

发生了负溢出,结果需要加上2ω,所以-2ω-1+(-2ω-1)= -2ω + 2ω = 0,所以-2ω-1的加法逆元就是其自身。

补码取非的技巧

将补码最右边的1的左边所有位按位取反,其他位保持不变。

3.无符号乘法

依然是截断低ω位得到结果

x 无符号* y = (x*y) mod 2ω

4.补码乘法

补码乘法和无符号数乘法的位级表示是相同的

补码乘法的结果就是无符号乘法的结果转为补码。

5.常数乘法

无符号整数乘以2的幂:x*2k,位表示的右边添k个0即可,即左移k位

补码同样左移k位即可。

发生溢出时,只需将移位结果截断即可。

例如,11的位表示为[1011],11*4=11*22,[1011]左移两位得到[101100],截断低4位得到[1100],即12=(11*4) mod 24

位操作在编译器中的应用

乘法的开销比加法和位移大得多,编译器往往希望用加减和位移来代替整数乘以常数的操作。

例如,x*14,会被优化为(x<<3)+(x<<2)+(x<<1)

除以2的幂

无符号除,逻辑右移k位,x>>k

补码除法,偏置

猜你喜欢

转载自www.cnblogs.com/CofJus/p/12201451.html
今日推荐