CSAPP 第二章 homework

2.57:

void show_short(short s);
void show_long(long long l);
void show_double(double d);
void show_bytes(char *p, int size);

void show_short(short s) {
    printf("the value of short %d is:", s);
    show_bytes((char *)&s, sizeof(short));
}

void show_long(long long l) {
    printf("the value of short %lld is:", l);
    show_bytes((char *)&l, sizeof(long long));
}

void show_double(double d) {
    printf("the value of short %lf is:", d);
    show_bytes((char *)&d, sizeof(double));
}

2.58:

/*
* 1 in little_endian
* *((char *)&i) means :
* 01 00 00 00 ----> 01 
*/
int is_little_endian() {
    int i = 1;
    return *((char *)&i);
}

2.59:

int graft(int x, int y) {
    return (x & 0xff) | (y & ~0xff); //或也可以改成+
}

2.60:

unsigned int graft2(unsigned int x,unsigned char y, int offset) {
    return (x & ~(0xff << (offset << 3))) | (((unsigned int)y) << (offset << 3));
}

2.61:

//A
return !~x;                    
//B
return !x;
//C
return !~((x >> ((sizeof(int) - 1) << 3)); 
//D
return !(x & 0xff);

2.62:

return ~((~0)>>1);        //~0 = -1

2.63:

int sra(int x, int k) {
    //arithmetically
    int xsrl = (unsigned) x >> k;
    unsigned first_bit = x & (0x1 << (sizeof(int) * 8 - 1));
    return xsrl + (((!first_bit) + ~0) << (sizeof(int) * 8 - k));
}

unsigned srl(unsigned x, int k) {
    //logically
    unsigned xsra = (int) x >> k;
    unsigned first_bit = x & (0x1 << (sizeof(int) * 8 - 1));
    return xsra & ~(~0 << (sizeof(int) * 8 - k));
}

2.64:

int any_even_one(unsigned x) {
    return !!(x & 0xaaaaaaaa);
}

2.65:

int even_ones(unsigned x) {
    x ^= (x >> 16);
    x ^= (x >> 8);
    x ^= (x >> 4);
    x ^= (x >> 2);
    x ^= (x >> 1);
    return !(x & 0x1);
}

2.66:

int leftmost_one(unsigned x) {
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return (x>>1) + 1;
}

2.67:

int int_size_is_32(){
    int set_msb = 1 << 31;
    int beyond_msb = (1 << 16) << 16;
    return set_msb && !beyond_msb;
}

int better_int_size_is_32() {
    int seb_msb = ((1 << 8) << 8) << 15;
    int beyond_msb = (((1 << 8) << 8) << 8) << 8;
    return seb_msb && !beyond_msb;
}

2.68:

//原题有点歧义,参数x没起到作用,于是把题目改成把x最低n位变成1
int lower_byte(int x, int n) {
    return x | ((unsigned)(~0) >> (sizeof(int) * 8 - n));
}

2.69:

unsigned rotate_right(unsigned x, int n) {
    return (x >> n) + ((x << (sizeof(int) * 8 - n - 1)) << 1);
}

2.70:

int fits_bits(int x, int n) {
    x >>= (n - 1);
    return !x || !(x + 1);
}

2.71:

 return ((int)word << (3 - bytenum << 3)) >> (3 << 3);

2.72:

A:size_t是无符号类型,在和int类型计算的时候,int类型会被转换,得出的结果也是无符号的,所以始终都大于0
B:maxbytes > 0 && maxbytes >= sizeof(val)

2.73:

int saturating_add(int x, int y) {
    int r = x + y;
    int tmp = r;
    int w = (sizeof(x) << 3) - 1;
    //x,y,r,取各自的符号位
    x >>= w;
    y >>= w;
    r >>= w;
    //正溢出时x,y为0,算数位移计算出的r为0xffffffff => 计算出pos_of = 0xffffffff
    int pos_of = (~x)&(~y)&r;
    //负溢出时x,y为0xffffffff,r为0
    int neg_of =  x & y & (~r);
    //统统使用位运算
    return (pos_of & TMAX) | (neg_of & TMIN) | tmp;
}

2.74

int tsub_ovf(int x, int y) {
    int r = x - y;
    x >>= (sizeof(int) << 3) - 1;
    y >>= (sizeof(int) << 3) - 1;
    r >>= (sizeof(int) << 3) - 1;
    return (x != y)&&(r == y);
}

2.75:

unsigned unsigned_high_prod(unsigned x, unsigned y) {
    //divide x(or y) into two parts the highest bit(xt or yt) and others(xr or yr) like this:
    //x => 0 000000000000000000000000000000
    //unsigned x * y = (xt * 2^31 + xr) * (yt * 2^31 + yr) = xr * yr + xt * 2^31 * yr + yt * 2^31 * xr + xt * yt * 2^62
    //and (unsigned) xr = (int)xr.So we can use the signed_high_prod() to calculate xr * yr
    unsigned xt = x >> sizeof(unsigned) - 1;
    unsigned yt = y >> sizeof(unsigned) - 1;

    unsigned xr = x & ~(1 << sizeof(unsigned) - 1);
    unsigned yr = y & ~(1 << sizeof(unsigned) - 1);

    return signed_high_prod(xr, yr) +
           (xt & yt) << 30 +
           (unsigned)(((int)xt << 31 >> 31) & yr) >> 1 +
           (unsigned)(((int)yt << 31 >> 31) & xr) >> 1 +
           add_of(xr * yr, (unsigned)(((int)xt << 31 >> 31) & yr) << 31,(unsigned)(((int)yt << 31 >> 31) & xr) << 31);
}

2.76:

1. x << 2 + x
2. x << 3 + x
3. x << 5 - x << 1
4. x << 3 - x << 6

2.77:

//c语言除法规则是向零舍去
int divide_power2(int i, int k) {
    return (i + ((1 << k) - 1) * (i < 0)) >> k;
}

2.78:

//参考了网上思路
//设x 为 b[w - 1], b[w - 2] ... b1, b0
//x * 5 => (x << 2) + x
//x * 5 / 8 = >
//(b[w - 3] ... b1, b0, 0, 0 + b[w - 1] ... b1, b0) >> 3 等价于
//b[w - 3] ... b1 + b[w - 1] ... b3 + (b1 & b2)
//并且 当x < 0时 需要进行舍入 也就是 x<0 && (x&0x7)时 结果需要加1
int mul5div8(int x) {
        int b0 = x & 1;
        int b2 = x & 0x4;
        int result = (x >> 1) + (x >> 3) + (b0 && b2);
        result += (x >> ((sizeof(int) << 3) - 1)) && (x&0x7);
        return result;
}
int main() {
        int i = 0x80000000;
        while(i < 0x7fffffff) {
            int ans_me = mul5div8(i);
            int ans_std = (long)5 * i / 8;
            if(ans_me != ans_std)
                        printf("%d %d %d\n", i, ans_me, ans_std);
            i++;
    }
}

2.80:

1. (~0) << n
2. ((~0) << m) + (0x1 <<(m + n))

2.81:

1. false y = TMIN
2. true
3. false x = 0, y = 0
4. true
5. true

2.82

nn=1Y2kn
2.83~2.90忘保存了..

2.91 ~ 2.96
工具函数

float u2f(unsigned u) {
        return *((float*)&u);
}
unsigned f2u(float f) {
        return *((unsigned*)&f);
}
int NaN(float_bits f) {
        int exp = (f>>23)       & 0xff;
        int frac = f            & 0x7fffff;
        return exp == 0xff && frac != 0;
}
int is_INF(float_bits f){
    int exp = (f>>23)       & 0xff;
    int frac = f            & 0x7fffff;
    return exp == 0xff && frac == 0;
}
int float_equal(float_bits f1, float f2) {
    return f1 == f2u(f2);
}
//测试函数,对于不同的题目需要进行相应的修改
int test(int (*fun1)(float_bits), int (*fun2)(float)) {
    unsigned u = 0;
    do{
        int me = fun1(u);
        int std = fun2(u2f(u));
        if(me != std)
        printf("error!!!\nu= %d, %x \nme is %x \nstd is %x \n", u, u, me, std);
        u++;
    }while(u!=0);
    printf("all finished");
    return 0;
}  

2.91:

//isnan 和 fabs 都是math.h中的方法
float_bits float_absval(float_bits f) {
    return NaN(f) ? f : f&~(1<<(sizeof(float_bits)<<3) - 1);
}
float myfabs(float f) {
    if(isnan(f)) return f;
    else return fabs(f);
}

2.92:

float_bits float_negate(float_bits f) {
    if(NaN(f)) return f;
    else return f + (1 << (sizeof(float_bits)<<3) - 1);
}
float myfneg(float f) {
    if(isnan(f)) return f;
    return -f;
}

2.93:

float_bits float_half(float_bits f) {
    if(NaN(f) || is_INF(f)) return f;

    unsigned sign = f & 0x80000000;
    unsigned exp  = f & 0x7f800000;
    if(exp > 0x00800000) return f - 0x00800000;
    f &= ~(1<<31); //需要位移 先舍去符号位
    //向偶数舍入
    unsigned b1 = f & 0x2;
    unsigned b0 = f & 0x1;
    b1 >>= 1;
    f >>= 1;
    f += (b1 & b0);
    return sign + f;
}

float myhalf(float f) {
    if(isnan(f)) return f;
    return f / 2;
}

2.94:

float_bits float_twice(float_bits f) {
    if(NaN(f) || is_INF(f)) return f;
    unsigned sign = f & 0x80000000;
    unsigned exp  = f & 0x7f800000;
    if(exp == 0) return (f << 1) + sign;            //非规格化时
    else if(exp == 0x7f000000) return sign + 0x7f800000;    //计算以后会产生溢出时
    return f + 0x00800000;
}

float mytwice(float f) {
    if(isnan(f)) return f;
    else return f*2;
}

2.95:

//乱的一比 等有时间再改改
float_bits float_i2f(int i) {
    if(i == 0) return 0;            //0
    if(i == 0x80000000) return 0xcf000000;  //TMin
    unsigned sign = i & 0x80000000;
    if(i < 0) i = -i;           //统一正负数
    unsigned x    = i &     0x7fffffff;
    unsigned exp  =     0x3f800000; //设置阶码为Bias(数值0)
    unsigned frac = 0;
    int pos = 0;    

    while((x>>=1)!=0)           //最高位所在的位置,0<=pos&&pos<=31
        pos++;
    x         = i & 0x7fffffff;
    if(pos <= 23)               //pos <= 23不需要考虑舍入的情况
        frac = (x<<23 - pos) & 0x007fffff;
    else{                   //需要考虑舍入,
        unsigned b0 = x & ~((~0) << pos - 23);
        unsigned b1 = (x >> pos - 23) & 1;
        if(b0 > (1 << pos - 24) || (b0 == (1 << pos - 24) && b1 == 1))
            x += (1 << pos - 23);
        frac = (x >> pos - 23) & 0x007fffff;
        //最容易被忽略的 在舍入中产生了进位
        if((x >> pos + 1) == 1) pos++;
    }
    exp += pos << 23;
    return sign + exp + frac;       
}

float myi2f(int i) {
    return (float)i;
}

2.96:

//做完上一题以后这道题就清爽了好多
#define BIAS 0x3f800000
int main() {
    test(float_f2i, myf2i);
    return 0;
}

int float_f2i(float_bits f) {
    int ans = 0;
    unsigned sign = f &     0x80000000;
    unsigned exp  = f &     0x7f800000;
    unsigned frac = f & 0x007fffff;
    frac +=         0x00800000;
    if(exp < BIAS) return 0;            //f < 1
    if(exp > BIAS + (30 << 23)) return 0x80000000;  //f > TMax

    int pos = (exp - BIAS) >> 23;
    if(pos <= 23) ans = frac >> 23 - pos;
    else ans = frac << pos - 23;
    return sign == 0 ? ans : -ans;
}

int myf2i(float f) {
    return f;
}

你可能感兴趣的:(csapp)