CSAPP LAB1 DataLab

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
}
發佈了169 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章