《深入理解计算机系统》这本书每章后面都有配套的CMU的课后lab,难度还是很高的。做这些lab一方面能够让自己更加深入理解本章的内容,看不如做。
本章的Data Lab限制了我们的编程方式,比如不让使用if,while等,让我们能够从不同的角度去思考问题,解法不唯一,但是这些解法带给我们的灵感是非常珍贵的。
第一部分是关于整数的题目,这部分限制只能使用0x00 - 0xff大小的常数,一般只允许使用!, &, |, <<, <<. ~等运算符。
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
//let 11 and 00 be 1&0 and 0&1, let 10 and 01 be 1&1
return (~(x&y)) & (~((~x)&(~y)));
}
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1<<31;
}
/*
* 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) {
//x+1 left shift 1 equal to 0, but x+1 don't equal to 0
return !(x+x+2) & !!(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) {
x = x & (x>>16);
x = x & (x>>8);
x = x & (x>>4);
x = x & (x>>2);
return (x>>1)&1;
}
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1;
}
/*
* 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: ! ~ & ^ | +i << >>
* Max ops: 15
* Rating: 3
*/
int isAsciiDigit(int x) {
int a = 0x30, b = 0x39;
int moreThan = !((x+(~a+1))&(1<<31));
int lessThan = !((b+(~x+1))&(1<<31));
return moreThan & lessThan;
}
/*
* 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 f = !x;
return ((f+~1+1)&y) | ((~f+1)&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) {
int a = x>>31;
int b = y>>31;
int c = a ^ b;
int diffSymbol = c&(a&1);
int sameSymbol = !c&!(((y+~x+1)>>31)&1);
return sameSymbol | diffSymbol;
}
/*
* 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; // 最后一个&1不能删,因为最高位为1的时候,算术右移补的都是1,不是0
}
/* 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 shift16, shift8, shift4, shift2, shift1, shift0;
int s = x>>31;//负数s=1,正数s=0
x = x ^ ((s<<31)>>31);//正数^ 0 ,负数 ^ 0xffffffff,这里用到了算术右移的性质
shift16 = (!!(x>>16))<<4;
x = x>>shift16;
shift8 = (!!(x>>8))<<3;
x = x>>shift8;
shift4 = (!!(x>>4))<<2;
x = x>>shift4;
shift2 = (!!(x>>2))<<1;
x = x>>shift2;
shift1 = (!!(x>>1));
shift0 = !!x;
return shift16 + shift8 + shift4 + shift2 + shift1 + shift0 + 1;
}
第二部分是关于浮点数的题目,这部分基本可以使用所有的常量以及运算符,if,while等关键字
//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) {
unsigned int s = uf & 0x80000000;
unsigned int exp = uf & 0x7f800000;
unsigned int frac = uf & 0x007fffff;
if(exp == 0x7f800000){
return uf;
}else if(!exp){
frac <<= 1;
}else {
exp = exp + (1<<23);
if(exp == 0x7f800000){
frac = 0;
}
}
return (s|exp|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){
int INF, s, exp, formatFrac;
INF = 1<<31;
s = uf>>31;
exp =(uf & 0x7f800000) >> 23;
formatFrac = uf & 0x00ffffff;
exp -= 127;
if(0 == uf || exp<0)
return 0;
if(exp > 31){
return INF;
}
if(exp > 23){
uf = formatFrac<<(exp-23);
}else{
uf = formatFrac>>(23-exp);
}
if(s){
uf = ~uf+1;
}
return uf;
}
/*
* 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;
}
总体来说这个Lab的题还是有一定挑战的,不仅能够让我们在读书过程中对书中的知识理解的更加深入,而且也能启发我们从不同的角度进行编程,体会位运算的神奇之处,毕竟对于计算机来说只有位运算才是最快的。
参考文献:曾参考此篇博客