CSAPP-DataLab

Datalab

本文是学习csapp第二章做的对应的Lab(DataLab),思路主要是来源于b站郭郭,个人认为讲的思路是很详细的,有兴趣的同学可以去b站看一下讲解

#endif
//1
/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
    //(a|b) & (~a|~b) rt
    return ~((~x)&(~y)) & (~(x & y));
}
/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
    //最小的(补码对应的)真值
    //补码:100000...00 
    //真值:-10000..000 ->32位
    return 1 << 31;
}
//2
/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
    //是否是补码的最大值
    //01111111..1111,判断是否相同
    /*
     * 原来不让用<<符号的鸭, 我傻了 
    x = ~x;
    int a = 1 << 31;
    x ^= a;
    return (!x);
    */
    //如果说不用设置新的变量能不能行
    //就要特判1111111..11
    return (!(~(x + 1) ^ (x))) & (!!(x + 1));
}
/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x) {
    //所有的都至少含有AAAAAAAA
    int A = 0xA;
    int AA  = A | (A << 4);     //用 | 将剩余的进行填充
    int AAAA  = AA | (AA << 8);
    int A8 = (AAAA | AAAA << 16);
    //将所有的偶数项目全部清除掉
    x = (x & A8);
    //如果所有奇数位置全部都是1,可以用异或与AAAA
    return !(x ^ A8);
  return 2;


}
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
 //所有的int都是用补码表示的
 //负数对应的二进制需要转换成为真值
 //1101 -> -3   取反:2
 //0010 -> 2    取反:-3
 return ~x + 1;         //按位取反 + 1
}
//3
/* 
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */
int isAsciiDigit(int x) {
    //1. 000000..11xxxx
    int cond1 = x >> 6;
    cond1 = !cond1;

    //2. 判断是否是11
    int cond2 = x >> 4;
    cond2 = !(cond2 ^ 0b11);

    //3. 最后四位是否小于10
    int cond3 = x & (0xF);      //拿到后四位
    cond3 = cond3 + (~0xa + 1);     //cond3 - A

    cond3 = cond3 >> 31;           //取到符号位,判断是否是1 -> 负号

    return cond1 & cond2 & cond3;

}
/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
    //实现三目运算符号
    //挺难的,根据掩码将两个运算符号同时出现
    //x | y 
    //思考:什么并或者交0 1 自身不变
  //  x = !!x;    //1或者是0
    //不是1 而是 111111111
    int mask = ((!!x) << 31) >> 31;
    //0 -> 00000000
    //1 -> 11111111
    return (mask & y) | ((~mask) & z);
}
/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y) {
  //1、符号相同就判断y-x的符号
  //2、符号不同 如果x小于0就是的了
  int result = y + (~x + 1);
  int signX = (x >> 31) & 1;
  int signY = (y >> 31) & 1;
  int sign = (signX ^ signY);       //如果同号就为0

  result = (result >> 31) & 1;

  return ((!sign) & !(result) ) | (sign & signX );
    //不同号,y-x >= 0             同号且x为负              

}
//4
/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int logicalNeg(int x) {
  //很巧妙的方法
  // a = 0111
  // -a = 1001
  //如果是0 的话 正负x的符号位都是0
  //否则正负x的符号位是相反的
  /*int negX = (~x + 1);
  int sign = (negX | x) >> 31;      //算术右移,左边31个全部用1填充
  //如果是0 sign = 00000000..00    ->真值是0
  //如果是1 sign = 11111111..11    ->真值是-1
  return sign + 1;
    */


    //如果是0的话,正负号的符号位都是0
    //如果是1的话,正负号的符号位是相反的
    int negX = ~x + 1;
    int sign = (negX | x) >> 31;
    //算术右移,
    return sign + 1;

}
/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */
int howManyBits(int x) {
  return 0;
  //不行,真的不会饿啦,自己去b站看看吧 :(
}
//float
/* 
 * floatScale2 - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned floatScale2(unsigned uf) {
    //if is leage
    //get sign expr frac
    unsigned s = (uf >> 31) & (0x1);
    unsigned expr = (uf >> 23) & (0xFF);
    unsigned frac = (uf & 0x7FFFFF);             //23bits

    //if uf == 0
    if (expr == 0 && frac == 0)
        return uf;

    //inif or NAN
    if (expr == 0xFF)
        return uf;

    //denomalize 
    if (expr == 0) {
        frac <<= 1;
        return (s << 31) | frac;    //expr == 0
    }

    //nomalize
    //expr +1  -> uf * 2
    expr++;
    return (s << 31) | (expr << 23) | (frac);
}
/* 
 * floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
int floatFloat2Int(unsigned uf) {

    unsigned s = (uf >> 31) & (0x1);            //符号位
    unsigned expr = (uf >> 23) & (0xFF);
    unsigned frac = (uf & 0x7FFFFF);             //23bits
    if (expr == 0 && frac == 0)
        return 0;
    //inf or NAN    
    if (expr == 0xFF) {
        return 1 << 31;                     //return 0x80000000
    }

    //Denomalize
    //E -> 1 - Bias = 1 - 127 = -126        
    //two small 
    if (expr == 0) {
        return 0;
    }

    //normalize
    int E = expr - 127;             //指数
    //加上前面的隐含的1(leading bit)
    frac |= (1 << 23);

    //判断E过大或者过小的情况
    if (E > 31) {
        return 1 << 31;     //爆int了
    }else if (E < 0){
        return 0;           //E是1.xxxxx   除以二后变为0了
    }


    //将指数部分乘到尾数上面(判断尾数左移或者右移几位)
    if (E >= 23) {
        frac <<= (E -23);
    }else {
        frac >>= (23 -E);
    }

    //最后判断符号位
    if (s) return ~frac + 1;            //按位取反加一
    return frac;

}
/* 
 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4
 */
unsigned floatPower2(int x) {
    //表示成为浮点数
    //denomalize E恒等于-126  frac 属于 [2^-23, 1)
    /*
     *最终denomarlize 的范围就是2 ^ -149 到 2 ^(-126) * (...) -> frac全部为1 
     *
     * normarlize 
     * 指数的范围是 -126 到 127
     *
     *
     * 乘上frac 范围是 2 ^ -126 
     * 最大数接近于 2 * 2 ^ 127
     *
     *
     * */
    //X就是指数,尾数是1,符号数是0
    if ( x < -149) {
        return 0;       //太小了
    }else if ( x < -126 ) {
        //denomarisze
        //指数X = 1 - 127 = -126
        int number = 23 + (x + 126);
        return 1 << number;
    }else if (x <= 127) {
        //指数X = expr - bias
        //我们求expr
        int expr = x + 127;
        return expr << 23;
    }else {         //inf
        return (0xFF) << 23;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值