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);
}
思路
异或运算的逻辑表达式是
对应的是
return (x&~y) | (~x & y);
然而本题不允许使用 “|” ,故需要将公式变形,得到上面结果
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);
}
思路
用四位来表示整数,可以发现:最大的数0111加1取反之后还是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
下面的几个实验都是关于浮点数的,关键就是这张图
/*
* 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>=31 或 E < 0), 返回0x80000000u 或 0,
然后处理在根据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.总结
这个实验对理解位运算、以及浮点数的表示非常有启发性