【CSAPP】 lab1 datalab

1.实验详解

1.1 bitXor

/* 
 * 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)&~(x&y);
}

思路
异或运算的逻辑表达式是
【CSAPP】 lab1 datalab
对应的是

return (x&~y) | (~x & y);

然而本题不允许使用 “|” ,故需要将公式变形,得到上面结果
【CSAPP】 lab1 datalab

1.2 tmin

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

1.3 isTmax

/*
 * 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+1)^x))&!!(x+1);
}

思路
用四位来表示整数,可以发现:最大的数01111取反之后还是0111。注意:1111 同样满足,故还要排除这种情况。

1.4 allOddBits

/* 
 * 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) {
    int a=0xAA<<8;
    int c=a|0xAA;
    int d=c<<16|c;
    return !((x&d)^(d));
}

思路
本题的题意是x如果满足:下标为奇数的位上全部为1(注意是从0开始数的)。所以,我们可以用0xAAAAAAAA来提取奇数位上的数,然后在和0xAAAAAAAA比较看是否相同。

1.5 negate

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

思路
A+~A=-1, A±A=0。 由两式可以推出:-A = ~A+1, 这个公式比较重要,在下面的实验会重复用到。

1.6 isAsciiDigit

/* 
 * 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 b=x&0xF;
    int c=~0xA+1;
    int e=0x80<<4;
    int d=!!((b+c)&(e));
    return  a&d ;
}

思路
观察 ‘0’ - ‘9’ 二进制的低8位:
0 : 0011 0000
9 : 0011 1001
可以发现:在两者之间的数满足两个条件:

  • 1.前面的4位 : 0011
  • 2.后面的4位 : 在0~9之间

对于第二个条件用后四位减去10,如果结果**< 0**,则证明条件2成立。

1.7 conditional

/* 
 * 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) {
  int a=!!(x^0x0); //a=0 if x=0 else a =1
  int b=~a+1;
  int c=~(y&~b)+1;
  int d=~(z&b)+1;
  return y+z+c+d;
}

思路
先判断x是否为0,如果为0让x=0xffffffff.

1.8 isLessOrEqual

/* 
 * 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 a=x>>31&0x1;
  int b=y>>31&0x1;
  int c1=(a&~b);  
  int c2=(~a&b);
  int e=y+(~x+1);  
  int flag=e>>31; 
  return c1 |(!c2&!flag);
}

思路
要考虑到溢出的情况,只有当两数的符号不同的情况下才会溢出。而且由于是lessOrEqual,两者相等的情况也要考虑到,所以用y-x比较方便

1.9 logicalNeg

/* 
 * 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) {
  return ((x | (~x +1)) >> 31) + 1;
}

思路
0相比与其他的数有一个特点:取反之后符号位的数与之前的不同

1.10 howManyBits

/* 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) {
  int flag = x >> 31;
  x = (~x & flag) | (x & ~flag); 
  int b16 = !!(x>>16)<<4;
  x>>=b16;
  int b8 = !!(x>>8)<<3;
  x>>=b8;
  int b4 = !!(x>>4)<<2;
  x>>=b4;
  int b2 = !!(x>>2)<<1;
  x>>=b2;
  int b1 = !!(x>>1);
  x>>=b1;
  int b0 = x;
  return b16+b8+b4+b2+b1+b0+1;
}

思路
对于正数 : 返回n+1(n为1的最高位)
对于负数 : 取反后,同正数做法
利用二分的思路找最高位

1.11 floatScale2

下面的几个实验都是关于浮点数的,关键就是这张图
【CSAPP】 lab1 datalab

/* 
 * 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) {
  unsigned sign = uf >> 31;
  unsigned exp = (uf & 0x7f800000) >> 23;
  unsigned frac = (uf & 0x7fffff);
  if (exp == 0xff) {
    return uf;
  } else if (exp == 0) {
    frac <<= 1;
    return (sign << 31) | (exp << 23) | frac;
  } else {
    exp++;
    return (sign << 31) | (exp << 23) | frac;
  }
}

思路
exp == 255, 返回 uf自身
exp == 0,属于非规格化浮点数
其他,exp++

1.12

/* 
 * 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 exp = (0x7f800000 & uf) >> 23;
  unsigned sign = uf & (0x1 << 31);
  unsigned frac = uf & (0x7fffff);
  int E = exp - 127;
  if (E < 0) return 0;
  else if (E >= 31) {
    return  0x80000000u;
  } else {
    frac = frac | (1 << 23);
    if (E > 23) {
      frac <<= (E - 23);
    } else{
      frac >>= (23 - E);
    }
  }
  if (sign) {
    return -frac;
  } else {
    return frac;
  }
}

思路
将浮点数转化为int
如果E超出正数所能表示的范围(即E>=31E < 0), 返回0x80000000u0
然后处理在根据E的大小,进行位移处理。

1.13

/* 
 * 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) {
    if (x > 127) {
      return 0xff <<23; 
    } else if (x <= -149) {
      return 0;
    } else if (x >= -126) {
      return (x + 127) << 23;
    } else {
      return ((0x1 << 23) >> (-x - 126)) | (1 << 23);
    }
}

思路
首先明确一下浮点数的表示范围:

  • 规格化 :2-126 ~ 2127
  • 非规格化 :2-149 ~2126

所以整体能表示的范围是:2-149 ~ 2127
2-149 ~ 2-125 用 非规格化表示,2-126 ~ 2-127 用 规格化表示

2.总结

这个实验对理解位运算、以及浮点数的表示非常有启发性

3.参考

周小伦(另外截取了两张图)
小土刀

上一篇:《CSAPP》虚拟内存笔记


下一篇:C# 委托事件, 发布者订阅者模式简单的demo