CSAPP LAB1 DataLab

来源:互联网 发布:.sit域名 备案 编辑:程序博客网 时间:2024/05/22 17:48

CSAPP LAB1 DataLab

用限定的运算符与结构实现一些功能,主要考察对位运算的了解,基本数据类型,浮点数,以及智商。

参考大佬1
参考大佬2
那个不用if的绝对值挺好的,据说可以加速绝对值计算,但是我测试并没有快多少>_<

int abs(int x){    int res=x>>31;    res=(x+res)^res;    return res;}

有一些太复杂了不想想了,就直接抄大佬了。用的时候再补吧~

/*  * CS:APP Data Lab  *  * <Please put your name and userid here> * Id:P.H.S * bits.c - Source file with your solutions to the Lab. *          This is the file you will hand in to your instructor. * * WARNING: Do not include the <stdio.h> header; it confuses the dlc * compiler. You can still use printf for debugging without including * <stdio.h>, although you might get a compiler warning. In general, * it's not good practice to ignore compiler warnings, but in this * case it's OK.   *//*  * bitAnd - x&y using only ~ and |  *   Example: bitAnd(6, 5) = 4 *   Legal ops: ~ | *   Max ops: 8 *   Rating: 1 */int bitAnd(int x, int y) {  //德摩根定律  return (~((~x)|(~y)));}/*  * getByte - Extract byte n from word x *   Bytes numbered from 0 (LSB) to 3 (MSB) *   Examples: getByte(0x12345678,1) = 0x56 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 6 *   Rating: 2 */int getByte(int x, int n) {  //移n没结果时要考虑移x  int tmp=(x>>(n<<3));  return tmp&0xff;}/*  * logicalShift - shift x to the right by n, using a logical shift *   Can assume that 0 <= n <= 31 *   Examples: logicalShift(0x87654321,4) = 0x08765432 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 20 *   Rating: 3  */int logicalShift(int x, int n) {  int k=~(1<<31);  int t;  k=((k>>n)<<1)|1;//左移n-1位,n为0就右移一位  t=k&(x>>n);  return t;}/* * bitCount - returns count of number of 1's in word *   Examples: bitCount(5) = 2, bitCount(7) = 3 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 40 *   Rating: 4 */int bitCount(int x) {  /*抄的,完全没思路*/  int count;  int tmpMask1 = (0x55)|(0x55<<8);   int mask1 = (tmpMask1)|(tmpMask1<<16);   int tmpMask2 = (0x33)|(0x33<<8);   int mask2 = (tmpMask2)|(tmpMask2<<16);   int tmpMask3 = (0x0f)|(0x0f<<8);   int mask3 = (tmpMask3)|(tmpMask3<<16);   int mask4 = (0xff)|(0xff<<16);   int mask5 = (0xff)|(0xff<<8);   count = (x&mask1)+((x>>1)&mask1);   count = (count&mask2)+((count>>2)&mask2);   count = (count + (count >> 4)) & mask3;   count = (count + (count >> 8)) & mask4;   count = (count + (count >> 16)) & mask5;   return count;  /*抄网上的,我个人习惯lowbit写法,需要用while  while(x)  {      x-=(x&(-x));      k++;  }  */}/*  * bang - Compute !x without using ! *   Examples: bang(3) = 0, bang(0) = 1 *   Legal ops: ~ & ^ | + << >> *   Max ops: 12 *   Rating: 4  */int bang(int x) {  int t=(~x)+1;//只有0x00000000和0x80000000按位取反+1等于本身,xor后等于0  int k=(x>>31)&1;//区分0x00000000和0x80000000  return 1^((((t^x)>>31)&1)|k);}/*  * tmin - return minimum two's complement integer  *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 4 *   Rating: 1 */int tmin(void) {  return 1<<31;}/*  * fitsBits - return 1 if x can be represented as an  *  n-bit, two's complement integer. *   1 <= n <= 32 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 15 *   Rating: 2 */int fitsBits(int x, int n) {//没懂题  n=32+(~n)+1;  return !(x^((x<<n)>>n));  /*先左移32-n位,在右移32-n位,即保留最后n位数。在与x异或  若两者相同表示x可被表示为一个n位整数,!0为1  */}/*  * divpwr2 - Compute x/(2^n), for 0 <= n <= 30 *  Round toward zero *   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 15 *   Rating: 2 */int divpwr2(int x, int n) {//补码右移本质是向负无穷取整    int m=x>>31;//x正数0x00000000,x负数0xffffffff    int k=(1<<n)+(~0);//(2^n)-1    x=x+(m&k);    return x>>n;}/*  * negate - return -x  *   Example: negate(1) = -1. *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 5 *   Rating: 2 */int negate(int x) {  //补码取负  return (~x)+1;}/*  * isPositive - return 1 if x > 0, return 0 otherwise  *   Example: isPositive(-1) = 0. *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 8 *   Rating: 3 */int isPositive(int x) {  return !((x>>31)|(!x));}/*  * 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) {  //先判符号,防止溢出,在做减法  int s1=(x>>31)&1;  int s2=(y>>31)&1;  int valid=s1^s2;  int res=y+(~x)+1;  return (((!(res>>31))&1)&(!valid))|(valid&(s1)&(!s2));}/* * ilog2 - return floor(log base 2 of x), where x > 0 *   Example: ilog2(16) = 4 *   Legal ops: ! ~ & ^ | + << >> *   Max ops: 90 *   Rating: 4 */int ilog2(int x) {  /*抄的,完全没思路*/    int bitsNumber=0;    bitsNumber=(!!(x>>16))<<4;//    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+8)))<<3);    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+4)))<<2);    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+2)))<<1);    bitsNumber=bitsNumber+(!!(x>>(bitsNumber+1)));    //for non zero bitsNumber, it should add 0    //for zero bitsNumber, it should subtract 1    bitsNumber=bitsNumber+(!!bitsNumber)+(~0)+(!(1^x));    //当x为0时,还需要减一才能得到正确值。    return bitsNumber;}/*  * float_neg - Return bit-level equivalent of expression -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 representations of *   single-precision floating point values. *   When argument is NaN, return argument. *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while *   Max ops: 10 *   Rating: 2 */unsigned float_neg(unsigned uf) {  unsigned tmp=uf&(0x7fffffff);  unsigned res=uf^(0x80000000);  if(tmp>(0x7f800000)) res= uf;  return res;}/*  * float_i2f - Return bit-level equivalent of expression (float) x *   Result is returned as unsigned int, but *   it is to be interpreted as the bit-level representation of a *   single-precision floating point values. *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while *   Max ops: 30 *   Rating: 4 */unsigned float_i2f(int x) {    /*抄的,太难写了*/    unsigned shiftLeft=0;    unsigned afterShift, tmp, flag;    unsigned absX=x;    unsigned sign=0;    //special case    if (x==0) return 0;    //if x < 0, sign = 1000...,abs_x = -x    if (x<0)    {        sign=0x80000000;        absX=-x;    }    afterShift=absX;    //count shift_left and after_shift    while (1)    {        tmp=afterShift;        afterShift<<=1;        shiftLeft++;        if (tmp & 0x80000000) break;    }    if ((afterShift & 0x01ff)>0x0100)        flag=1;    else if ((afterShift & 0x03ff)==0x0300)        flag=1;    else        flag=0;    return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag;}/*  * float_twice - 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 float_twice(unsigned uf) {    unsigned f = uf;    if ((f & 0x7F800000) == 0) //指数是0,特殊小数    {        //左移一位        f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);    }    else if ((f & 0x7F800000) != 0x7F800000)//一般浮点数,直接加阶码    {        f =f + 0x00800000;    }    return f;//剩下NAN}