CSAPP(深入理解计算机系统)第二版家庭作业答案-第二章

  • Post author:
  • Post category:其他


答案均由本人完成,并且实验或者调试,欢迎参考!

2.55-2.57
略


2.58
int is_little_endian(){
int i=1;
return *((char*)&i);
}


2.59
int test_2_59(int x,int y){
return (x&0xff)|(y&(~0xff));
}


2.60
unsigned replace_byte(unsigned x,unsigned char b,int i){
    unsigned int mask=0xff;
    unsigned int val=b;
    unsigned int shift_val=i<<3;
    mask=mask<<shift_val;
    val=val<<shift_val;
    return (x&~mask)|val;
}


2.61
A.
!~x;
B.
!x;
C.
!~(x>>24)
D.
!(x&0xff)


2.62
bool int_shifts_are_logical(){
int x=-1;
x=x>>(sizeof(int)<<3-1);
return !~x; 
}


2.63
int sra(int x,int k){
    int xsrl=(unsigned)x>>k;
    int w=sizeof(int)<<3;
    //if(x<0)
    //    return xsrl|~((1<<(w-k-1))-1);
    //return xsrl;
//不用逻辑运算符
int z=1<<(w-k-1);
return xsrl|~((z&xsrl)-1);
}




unsigned srl(unsigned x,int k){
    unsigned xsra=(int)x>>k;
    int w=sizeof(int)<<3;
    return xsra&((1<<(w-k))-1);
}


2.64
//求任意偶数位是否为1,从0开始计算
int any_even_one(unsigned x){
while(x){
if(x&1)
return 1;
x=x>>2;
}
return 0;
}


2.65
//求是否包含偶数个1
int even_ones(unsigned x){
int w=32;
while(w>1){
w=w>>1;
x=(x>>w)^x;
}
return !(x&1);
}


2.66
//求最高有效位的1
int leftmost_one(unsigned x){
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);  //这里一定会得到从最高位的1到最低位的全部为1
    return x^(x>>1);
}


2.67
A.在int为32位的机器上不应该左移32位
B.
int bad_int_size_is_32(){
int set_msb=1<<31;
return set_msb && set_msb<0;
}
C.
int bad_int_size_is_32(){
int z=1<<15;
z=z<<15;
int set_msb=z<<1;
int beyond_msb=z<<2;
return set_msb && !beyond_msb;
}

2.68
int lower_bits(int x,int n){
return x&((2<<(n-1))-1);
}


2.69
unsigned rotate_right(unsigned x,int n){
int w=sizeof(unsigned)<<3;
return x>>n | x<<(w-n-1)<<1;
}


2.70
int fits_bits(int x,int n){
x=x>>(n-1); //x全为1或者全为0能表示 
return !(x && ~x);
}


2.71
A.
word是unsigned类型所以会进行无符号扩展,比如原字节是0xff(-1),这个函数将返回0xff(255),而非题目要求
B.
int xbyte(packed_t word,int bytenum){
return ((int)(word<<((3-bytenum)<<3)))>>24;
}




2.72
A.size_t是unsigned类型,相减结果会提升至unsigned,而unsigned类型总是>=0
B.
void copy_int(int val,void *buf,unsigned maxbytes){
if(maxbytes>=sizeof(val))
memcpy(buf,(void*)&val,sizeof(val));
}


2.73
int saturating_add(int x,int y){
int sum=x+y;
if( x>=0 && y>=0 && sum<0)
return INT_MAX;
if(x<0 && y<0 && sum>=0)
return INT_MIN;
return sum;
}


2.74
int tsub_ovf(int x,int y){
int sub=x-y;
if(x >=0 && y<0 && sub<0)
return 1;
if( x<0 && y>=0 && sub>=0)
return 1;
return 0;
}


2.75
unsigned unsigned_high_prod(unsigned x,unsigned y)  
{  
    int w = sizeof(unsigned) << 3;  
int sx=(int)x;
int sy=(int)y;
int t= signed_high_prod(sx,sy);
return t+ ((sx>>(w-1))&1)*sy+((sy>>(w-1))&1)*sx;  
}


2.76
A.
(x<<2)+x
B.
(x<<3)+x
C.
(x<<5)-(x<<1)
D.
(x<<3)-(x<<6)


2.77
int divide_power2(int x,int k){
int bias= (x>>31) & ((1<<k)-1);
return (x+bias)>>k;
}


2.78
int mul5div8(int x){
int x=(x<<2)+x;
int bias= (x>>31) & 7;
return (x+bias)>>3;
}


2.79
int fiveeighths(int x){
int bias= (x>>31) & 7;
x=(x+bias)>>3;
return (x<<2)+x;
}


2.80
A.
~((1<<n)-1)
B.
((1<<n)-1)<<m


2.81
A.
x=0,y=Tmin
B.
总为1,位级表示相同
C.
~x=-x-1
~y=-y-1
~(x+y)=-x-y-1
-x-1-y-1!=-x-y-1
总为0
D.
总为1,无符号和有符号减法位级表示相同,而且最后都转成int类型,结果一致
E.
总为1,右移再左移必有1位丢失或者不丢失,丢失的这1位权值为正,值会变小


2.82
A.
等比数列求和a1*(1-q^n)/(1-q)
a1=Y/(2^k) q=1/(2^k)
假设n非常大,1-q^n可看作1
a1/(1-q)
所以通项公式是Y/(2^k-1)
B.
y=001 1/7
y=1001 3/5
y=000111 1/9

2.83
return sx==sy?(ux==uy)||((ux>uy)^sx):((ux<<1)==0 && (uy<<1)==0)||sx<sy;
或者
return ((ux<<1)==0 && (uy<<1)==0) || 
(!sx && sy) || 
(!sx && !sy && ux >= uy) ||
(sx && sy && ux <= uy);


2.84
A.
E M fV
2 1.01 0.01 5
e=1+2^(k-1)
f=01000..00
B.
E M fV
n 1.111.. 0.11.. 2^(n+1)-1
e=n+2^(k-1)-1
f=11111..11
C.
E M fV
2^(k-1)-2 1 0 2^(2^(k-1)-2)
e=2^k-3
f=0




2.85
最小的正非规格化数:2^(-2^14+2)*1/2^63
最小的正规格化数:2^(-2^14+2)
最大的规格化数:2^(2^14-1)*(2-1/2^63)




2.86
描述 Hex M E V
-0 0x8000 0 -62 --
最小的值>1 0x3f01 257/256 0 257*2^(-8)
256 0x4700 1 8 --
最大的非规格化数 0x00ff255/256 -62255*2^(-70)
负无穷 0xff00 -- -- --
0x3AA0 -- 13/8 -5 13*2^(-8)


2.87
格式A 格式B
位 值 位值
1 01110 001 -9/161 0110 0010 -9/16
0 10110 101 208 0 1110 1010208
1 00111 110 -7/10241 0000 0111     -7/1024
0 00000 101 3/(2^17)0 0000 0001 1/(2^10)
1 11011 000 -2^12 1 1111 0000负无穷
0 11000 100 3*2^80 1111 0000 正无穷
       


2.88
A.0
x转float有精度丢失,x=2^24+1=16777217
B.0
x=Tmax,y=Tmax,x+y溢出得到负数,而dx+dy不溢出
C.1
double可精确表示2^53内的所有整数,而相加不可能超出这个范围
D.0
32位乘法可能导致结果超出2^53,会导致舍入
E.0
dx或dy为0




2.89
float fpwr2(int x){
unsigned exp,frac;
unsigned u;
if(x<-149){
exp=0;
frac=0;
}
else if(x<-126){
exp=0;
frac= 1<<(149+x);
}
else if(x<128){
exp=x+127;
frac=0;
}
else{
exp=255;
frac=0;
}
u=exp<<23|frac;
return u2f(u);
}


2.90
0x40490fdb
0100 0000 0100 1001 0000 1111 1101 1011
A.
11.0010010000111111011011
B.
11.001001001001001001001001..
C.
从低9位,即2^(-9)


2.91
float_bits float_absval(float_bits f){
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp==0xff && frac!=0)
return f;
return f&0x7fffffff;
}


2.92
float_bits float_negate(float_bits f){
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp==0xff && frac!=0)
return f;
return f^0x80000000;
}


2.93
float_bits float_half(float_bits f){
unsigned sign=f>>31;
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp==0xff && frac!=0)
return f;
if(exp==0xff && frac==0)
return f;       //正无穷或者负无穷
if(exp ==0 || exp==1)
{
if(exp==1)
frac=frac|0x800000;
if((frac & 3)==3)
frac=(frac+1)>>1;
else
frac=frac>>1;
}
if(exp>0) {
exp-=1;
}
return (sign<<31) | (exp<<23) | frac;
}


2.94
float_bits float_twice(float_bits f){
unsigned sign=f>>31;
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp==0xff && frac!=0)
return f;
if(exp==0xff && frac==0)
return f;       //正无穷或者负无穷
if(exp ==0)
{ 
frac=frac<<1;
}
else{
exp+=1;
if(exp==0xff)
frac=0;
}
return (sign<<31) | (exp<<23) | frac;
}


2.95
float_bits float_i2f(int i){
if(i==0)
return 0;
unsigned sign=0;
unsigned frac=i;
if(i&0x80000000){
sign=1;
frac=~frac+1;
}
unsigned c=0;
while (!(frac&0x80000000))
{
frac=frac<<1;
++c;
}
unsigned exp= (31-c)+127;
frac=frac<<1;
frac=(frac>>9)+((frac&0x100)&&((frac&0x200)||(frac&0xff)));//向偶数舍入,进位
if(frac&0x800000) //如果进位
++exp;


return (sign<<31) | (exp<<23) | (frac&0x7fffff);
}


2.96
int float_f2i(float_bits f){
unsigned sign=f>>31;
unsigned exp=f>>23&0xff;
unsigned frac=f&0x7fffff;
if(exp<0x7f)
return 0;
else if(exp>158 ||(exp==158&&frac>0))
return 0x80000000;
int c=exp-0x7f;
if(c>23)
frac= ((1<<23)|frac)<<(c-23);
else
frac= (frac>>(23-c))|(1<<c);
return sign?(~frac+1):frac;
}

原创地址:

http://blog.csdn.net/maidou0921/article/details/53907832



版权声明:本文为maidou0921原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。