《深入理解计算机系统》 练习题2.42-2.44 补码除以2的幂
补码除以2的幂
具体讲解在书里。这里直接给几个结论:
1)有符号数即补码数执行的是,算术右移。
2)有变量x和(0<=k<w),那么将产生数值。
3)正常来说,除法是向零取整,而不是固定的向下取整。所以为了负数除法有正确的结果,在移位前加偏置。所以,当x为负数时,将执行产生数值。
将当做y,所以就是=
关于第3条结论,除了书中给出的证明,这里给出一个直观上的解释:
假如现在是一个负的小数,y为4,且可以分解为-3和,本来-2.75向下取整是-3,就不是向零取整了。但这里再加上一个,结果就会变成-2,再向下取整,也是正确的结果-2了。
而且上面的分解过程,是大于等于,小于等于,所以肯定能保证正确结果。
2.42原理
当x为非负数时,不加偏置。因为此时的向下取整就是向零取整。
当x为负数时,加偏置。
具体来说,就是得到x的符号位上的值是0还是1,如果是1,那么就要加上偏置即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 = -1,最后的右移操作也是右移3位,所以N为即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位的权值,且正溢出结果必为负数。
但这里就不一样了,因为乘积的结果可能很大。正溢出的结果也是可能正,可能负。
规律如下:
将乘积设为s,如果s-为负数,那么s-则为溢出结果。
如果s-为非负数,那么(s-)%则为溢出结果。
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=(TMAX).
x+y = -2 ,再转无符号明显是(TMAX-1,除最低一位为0外,其余都为1)
x+y = ()*2 - = - 2 - = .
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