《深入理解计算机系统》 练习题2.42-2.44 补码除以2的幂

补码除以2的幂

具体讲解在书里。这里直接给几个结论:
1)有符号数即补码数执行的是,算术右移。

2)有变量x和 2 k 2^k 2k(0<=k<w),那么 x &gt; &gt; k x &gt;&gt;k x>>k将产生数值 ⌊ x / 2 k ⌋ \lfloor {x/2^k} \rfloor x/2k

3)正常来说,除法是向零取整,而不是固定的向下取整。所以为了负数除法有正确的结果,在移位前加偏置。所以,当x为负数时,将执行 ( x + ( 1 &lt; &lt; k ) − 1 ) &gt; &gt; k (x + (1&lt;&lt;k)-1) &gt;&gt;k (x+(1<<k)1)>>k产生数值 ⌈ x / 2 k ⌉ \lceil {x/2^k} \rceil x/2k
2 k 2^k 2k当做y,所以就是 ⌈ x / y ⌉ \lceil x/y \rceil x/y= ⌊ ( x + y − 1 ) / y ⌋ \lfloor (x+y-1)/y \rfloor (x+y1)/y

关于第3条结论,除了书中给出的证明,这里给出一个直观上的解释:
( x + y − 1 ) / y = x y + y − 1 y (x+y-1)/y =\frac{x}{y} + \frac{y-1}{y} (x+y1)/y=yx+yy1
假如 x y \frac{x}{y} yx现在是一个负的小数,y为4, x y \frac{x}{y} yx且可以分解为-3和 1 4 \frac{1}{4} 41,本来-2.75向下取整是-3,就不是向零取整了。但这里再加上一个 3 4 \frac{3}{4} 43,结果就会变成-2,再向下取整,也是正确的结果-2了。
而且上面的分解过程, ? 4 \frac{?}{4} 4是大于等于 1 4 \frac{1}{4} 41,小于等于 4 − 1 4 \frac{4-1}{4} 441,所以肯定能保证正确结果。

2.42原理

当x为非负数时,不加偏置。因为此时的向下取整就是向零取整。
当x为负数时,加偏置。

具体来说,就是得到x的符号位上的值是0还是1,如果是1,那么就要加上偏置 2 4 − 1 2^{4}-1 241即15。

2.42代码

int book_div16(int x)
{
        /* Compute bias to be either 0 (x >= 0) or 15 (x < 0) */
        int bias = (x >> 31) & 0xF;//右移31位后,32位上面都是符号位的值
        //如果为非负数,符号位为0,bias变量为0
        //如果为负数,符号位为1,bias变量为0xF,即15
        return (x + bias) >> 4;
}

如上为原书实现。

2.43

在这里插入图片描述
先看M:
代码等价于x = x * 32 -x = x * 31.所以M为31.
再看N:
7 = 2 3 2^3 23-1,最后的右移操作也是右移3位,所以N为 2 3 2^3 23即8.

2.44

int x = foo();
int y = bar();
unsigned ux = x;
unsigned uy = y;
对于以下的各表达式,回答两个问题:(1)对于任意的x和y值,该表达式是否为true,
(2) 当x和y取什么值时为false

A. (x > 0) || (x-1 < 0)
当x为TMIN时,左边不符合条件,为0;右边负溢出为TMAX,正数不小于0,为0;此时为false

B. (x & 7) != 7 || (x<<29 < 0)
左边要求的是x的低3位不能都为1;右边要求第3位为1(先左移29位,所以有原始的低3位和29位个0组成,此时小于0,说明符号位为1,即原始的低3位的最高那个为1);
低3位分两种情况:
1)除111外的所有情况:左边符合,必返回1,不用管右边。
2)111:左边不符合,但右边符合了,也返回1。
该表达式必为true。

C. (x * x) >= 0
很明显会出现正溢出,但这里和加法的溢出不一样,加法正溢出最多能获得第w+1位的权值 2 w 2^w 2w,且正溢出结果必为负数。
但这里就不一样了,因为乘积的结果可能很大。正溢出的结果也是可能正,可能负。
规律如下:
将乘积设为s,如果s- 2 w 2^w 2w为负数,那么s- 2 w 2^w 2w则为溢出结果。
如果s- 2 w 2^w 2w为非负数,那么(s- 2 w 2^w 2w)% 2 w 2^w 2w则为溢出结果。

	short a, b, c;
	a = b = 182;
	c = a * b;

在这里插入图片描述
182*182-65536=33124-65536=-32412

	short a, b, c;
	a = b = 270;
	c = a * b;

在这里插入图片描述
(270*270-65536)%65536=(72900-65536)%65536=7364%65536=7364

	short a, b, c;
	a = b = 400;
	c = a * b;

在这里插入图片描述
(400*400-65536)%65536=(160000-65536)%65536=94464%65536=28928
非要说原因的话,就是加法正溢出会导致第w位的值为1,而乘积正溢出就不一定了。

D. x<0 || -x <= 0
当x为0时,右边成立;
当x为[1,TMAX],右边必成立;
当x为[TMIN+1,-1],左边成立;
当x为TMIN,左右都成立;
综上,此表达式必为1.

E. x>0 || -x >= 0
当x为0时,右边成立;
当x为[1,TMAX],左边成立;
当x为[TMIN+1,-1],右边成立;
当x为TMIN,左右都不成立;

F. x+y == uy+ux
表达式中含有无符号数,所以左边也会转换为无符号数。等价于unsigned(x+y) == uy+ux.
在二进制上,无符号数和有符号数的加法是一样的,故都为真。
例如:x=y=-1,则ux=uy= 2 32 − 1 2^{32}-1 2321(TMAX).
x+y = -2 ,再转无符号明显是 2 32 − 2 2^{32}-2 2322(TMAX-1,除最低一位为0外,其余都为1)
x+y = ( 2 32 − 1 2^{32}-1 2321)*2 - 2 32 2^{32} 232 = 2 33 2^{33} 233 - 2 - 2 32 2^{32} 232 = 2 32 − 2 2^{32}-2 2322.

G. x*~y + uyux == -x
-y = ~y+1,故 ~y=-y-1, 左边= x
(-y-1)+uyux = uyux - xy -x, 不管是无符号数还是有符号数,在二进制层面上相乘后截短后的结果都是相同的。故 uyux-x*y=0, 故结果都为真,道理同上。

参考链接:
[1] https://github.com/haiiiiiyun/book_exercises/blob/master/csapp-v3/chap2/2.43-2.54.txt

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值