1. 程式人生 > >CS:APP Data Lab

CS:APP Data Lab

使用方法

1.編寫bits.c,然後編譯

unix> ./dlc -e bits.c

dlc:bits.c:147:bitXor: 8 operators
dlc:bits.c:158:tmin: 1 operators
dlc:bits.c:169:isTmax: 7 operators
dlc:bits.c:185:allOddBits: 10 operators
dlc:bits.c:196:negate: 2 operators
dlc:bits.c:214:isAsciiDigit: 14 operators
dlc:bits.c:226:conditional: 7 operators
dlc:bits.c:243:isLessOrEqual: 18 operators
dlc:bits.c:261:logicalNeg: 12 operators
dlc:bits.c:306:howManyBits: 37 operators
dlc:bits.c:327:floatScale2: 9 operators
dlc:bits.c:355:floatFloat2Int: 23 operators
dlc:bits.c:375:floatPower2: 5 operators

2.執行和評分 (每次修改bit.c後都要重新編譯btest)

unix> make btest && ./btest

Score   Rating  Errors  Function
    1       1       0   bitXor
    1       1       0   tmin
    1       1       0   isTmax
    2       2       0   allOddBits
    2       2       0   negate
    3       3       0   isAsciiDigit
    3       3       0   conditional
    3       3       0   isLessOrEqual
    4       4       0   logicalNeg
    4       4       0   howManyBits
    4       4       0   floatScale2
    4       4       0   floatFloat2Int
    4       4       0   floatPower2
Total points: 36/36

參考程式碼

整數

bitXor: 計算x^y

/* bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
  return ~( ~(~x&y) & ~(~y&x)); // x^y = (~x&y) | (x^~y) 
}

tmin: 返回最小的32位有符號數

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {

  return 1<<31;

}

isTmax: 判斷一個數是不是最大的32位有符號數

/*
 * 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) {
  return !(x+x+2) & !!(~x) ;   //x !=-1 && x+x+2 == 0
}

allOddBits: 判斷二進位制表示中是否所有的奇數位都是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
 *   二進位制表示中所有的奇數位都是1
 */
int allOddBits(int x) {
    x = (x>>16) & x;
    x = (x>>8) & x;
    x = (x>>4) & x;
    x = (x>>2) & x;
    return (x>>1)&1;
}

negate: 返回-x

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 *   返回-x
 */
int negate(int x) {
  return ~x+1;
}

isAsciiDigi: 判斷一個數是否在[0x30,0x39]範圍內

/* 
 * 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) {
  int a = (x>>4) ^ 0x3;
  int b0 = (x>>3) & 1;
  int b1 = (x>>2) ^ 1;
  int b2 = (x>>1) ^ 1;

  return (!a) & ((!b0) | (b0&b1&b2));
}

conditional: 實現 x ? y : z

/* 
 * 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 = !x;
  x = (x<<31)>>31;//把x擴充套件到31位
  return (~x&y) | (x&z);
}

isLessOrEqualisLessOrEqual 返回a<=b

/* 
 * 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 z,s,sx,sy;
  sx = (x>>31)&1;
  sy = (y>>31)&1;
  z = x + ~y + 1; //x-y
  s =  ((z>>31) & 1) | (!(z^0)); //負數或者0
  //x和y符號相同時看差的符號
  //x<0 && y >=0 返回true
  return  ((!(sx^sy))&s) | (sx&(!sy));
}

logicalNeg: 返回一個數的邏輯值,0=flase,非0=true

/* 
 * 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) {
  x |= x>>16;
  x |= x>>8;
  x |= x>>4;
  x |= x>>2;
  x |= x>>1;
  x ^= 1; 
  return x&1;
}

howManyBits:返回用補碼錶示x需要至少幾位

/* 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
 */
//如果是正數的話就直接,二分最高位的1,然後再+1
//如果是負數取反
int howManyBits(int x) {
  int s,c1,c2,c3,c4,c5,c6;
  int cnt = 0;
  s = (x>>31)&1;
  x = ((s<<31)>>31) ^ x;

  s = !!(x>>16);  //高16位是否非0
  c1 = s<<4;      //非0的話右移16位
  x >>= c1;       

  s = !!(x>>8);
  c2 = s<<3;
  x >>= c2;

  s = !!(x>>4);
  c3 = s<<2;
  x >>= c3;

  s = !!(x>>2);
  c4 = s<<1;
  x >>= c4;

  s = !!(x>>1);
  c5 = s;
  x >>= c5;

  c6 = !!x;
  cnt = c1+c2+c3+c4+c5+c6+1;
  return cnt;
}

float

floatScale2: 返回2*f

/* 
 * 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
 * 返回2*f
 */
unsigned floatScale2(unsigned uf) {
  unsigned f = uf;
  if ((f & 0x7F800000) == 0)  //如果階碼為0時,尾數左移1位
    f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
  else if ((f & 0x7F800000) != 0x7F800000) //階碼不等於128時,階碼+1
     f =f + 0x00800000;
  return f;   //NaN
}

floatFloat2Int: float轉化成int

/* 
 * 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 INF = 1<<31;
  int e = (uf>>23) & 0xff;
  int s = (uf>>31) & 1;
  if (uf == 0) return 0;
  uf <<= 8;
  uf |= 1<<31;
  uf >>= 8;
  e -= 127;
  if ((uf & 0x7f80000) == 0x7f80000 || e >= 32) return INF;
  if (e < 0) return 0;
  if (e <= 22) uf >>= 23-e;
  else uf <<= e-23;
  if (s) uf = ~uf + 1;
  return uf;
}

floatPower2: 返回pow(2,x)

/* 
 * 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) {
  unsigned INF = 0xff << 23;
  int e = 127 + x;
  if (x < 0) return 0;
  if (e >= 255) return INF;
  return e << 23;
}