参考资料:
CSAPP:Lab1 -DataLab 超详解 - 知乎 (zhihu.com)
Guo749/CSAPP: My Notes for CSAPP (github.com)
1. bitXor
德摩根律的应用

//1
/*
* 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);
}
2. tmin
// tmin - return minimum two's complement integer
int tmin(void) {
return 1<<31;
}
3. tmax
题意:如果x用二进制表示是最大值,那么return 1, else return 0
题解:若x为最大值,那么x的二进制表示满足:
- 首位为0
- 其余位为1
例如0111 1111
若满足上述条件,有x+1 = 100…,于是 !(x+1) = x,判断是否相等可以用异或操作。
注意当x=-1时,上式依然满足,因为 -1=1111 ,故需特判 x!=-1, 观察1111可知x+1=0。
// isTmax - returns 1 if x is the maximum, two's complement number,and 0 otherwise
int isTmax(int x) {
return !(~(x+1)^x)&!!(x+1);
}
4. isTmax
题意:奇数位全为1,return 1,注意数字下标从0开始
题解:只需构造一个101010…的二进制数,然后&x,如果&之后的结果有变化,那么奇数位存在0,由题3可知用异或操作可判断两个数之间是否相等。
// 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
int allOddBits(int x) {
int m = 0xAA << 8;
m = m | 0xAA;
m = (m << 16) | m;
return !((m&x)^m) ;
}
5. negate
// negate - return -x
int negate(int x) {
return ~x + 1;
}
6. isAsciiDigit
题解:判断该范围有两步:
- 除后四位外其余位相等
- 后四位在0到9之间
第一步,只需判断相应位是否与0x3相等即可;
第二步,这里可用一些技巧,0到9任意数-10都为负数,故只需提取出后四位-0xA,判断最高位是否为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.
int isAsciiDigit(int x) {
int a = !((x >> 4) ^ 0x3);
int b = x & 0xF;
int c = ~0xA + 1;
int d = !!((b + c) & (1 << 31));
return a & d;
}
7. conditional
题解:通过x是否为0构造出全0二进制数或全1二进制数,然后去选择y,z。
这里注意1111… + 1 = 0
// conditional - same as x ? y : z
// Example: conditional(2,4,5) = 4
int conditional(int x, int y, int z) {
int m = ~(!x) + 1;
return (~m & y) | (m & z);
}
8. isLessOrEqual
题解:本题需解决的问题是符号位的判断。
- 取出符号位
- 判断不同号时的合适条件
- 分情况讨论:
- 相等
- 不同号且
x<0,y>0 - 同号且
x<y
// isLessOrEqual - if x <= y then return 1, else return 0
// Example: isLessOrEqual(4,5) = 1.
int isLessOrEqual(int x, int y) {
int equal = !(x ^ y);
int signX = (x >> 31) & 1;
int signY = (y >> 31) & 1;
int cond1 = !(signX) & (signY); // cond1 = 0 -> (signX < signY 或者同号) else signX > signY
int cond2 = (signX) & !(signY);
int sameSign = !(signX ^ signY);
int res = x + ~y + 1;
int greater = (res >> 31) & 1;
return equal | ((!cond1) & (cond2 | (greater & sameSign)));
}
9. logicalNeg
题解:对x求其负数,若x为正数则符号位为1,若为0和负数则为0;那么要区分0和负数可以将(negX | x),这样便将负数的情况归为符号位为1的情况;之后右移31位,可知0不变,其余情况均为-1。
/*
* 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
!0, 0
int a = 0111;
int -a = 1001;
int sign = 1
*/
int logicalNeg(int x) {
int negX = ~x + 1;
int sign = (negX | x) >> 31;
return sign + 1;
}
10. howManyBits
题意:返回在二进制补码中表示 x 所需的最小位数
题解:
- 明确所需最小位数就是除符号位的最高有效位1,那么需要对x进行初始化,以便提取出这个最高位(-1的二进制补码表示为0xFF)
x = (flag & (~x)) | ((~flag) & 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
*/
int howManyBits(int x) {
int isZero = !x;
int flag = x >> 31;
x = (flag & (~x)) | ((~flag) & x);
int bit_16, bit_8, bit_4, bit_2, bit_1, bit_0;
b16 = !!(x>>16) << 4; //如果高16位不为0,则我们让b16=16
x >>= b16; //如果高16位不为0 则我们右移动16位 来看高16位的情况
//下面过程基本类似
b8 = !!(x>>8) << 3;
x >>= b8;
b4 = !!(x >> 4) << 2;
x >>= b4;
b2 = !!(x >> 2) << 1;
x >>= b2;
b1 = !!(x >> 1);
x >>= b1;
b0 = x;
int res = bit_0 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16 + 1;
return isZero | res;
}
11. floatScale2


题意:给定f,返回2*f
题解:
- 取出三个字段的值
- 分类讨论
- 无穷大和NaN为一类
- 0为一类
- 非规格化时,f不为0,只需将f编码的尾数M乘2即可
- 规格化时,将expr++即可,因为
E = expr - bias,expr++相当于E++,即V*2
/*
* 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) {
//expr, s, frac
unsigned s = (uf >> 31) & (0x1);
unsigned expr = (uf >> 23) & (0xFF);
unsigned frac = (uf & 0x7FFFFF);
//0
if(expr == 0 && frac == 0)
return uf;
//inifity or nor na number
if(expr == 0xFF)
return uf;
//denormalize
if(expr == 0){
//E = expr - 127 = -127
//frac
frac <<= 1;
return (s << 31) | frac;
}
//normalzie
expr++;
//E = expr - 127
return (s << 31) | (expr << 23) | (frac);
}
12. floatFloat2Int
题意:浮点数转化为整型
题解:除规格化数,其余基本同上题;
当为规格化数时,按照定义如下步骤:
- 尾数编码加上隐含的1,求出阶码值E
- 按照阶码值大小分类讨论:
- 对于单精度数,E>31为无穷大,E<0转整型为0
- 因为尾数编码有23位,故E>=23时,故需对尾数乘
2^E,即左移E-23位,E<23时,右移23-E位即可 - 最后根据符号位求其负数或不变即可
/*
* 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 s = (uf >> 31) & (0x1);
unsigned expr = (uf >> 23) & (0xFF);
unsigned frac = (uf & 0x7FFFFF);
//0
if(expr == 0 && frac == 0)
return 0;
//Ini / NaN
if(expr == 0xFF)
return 1 << 31;
//denormalzie
if(expr == 0){
//M 0.1111 < 1
//E = 1 - 127 = -126
return 0;
}
//noramlzie
int E = expr - 127;
frac = frac | (1 << 23);
if(E > 31) //1.XXXX
return 1 << 31;
else if(E < 0){
return 0;
}
if(E >= 23){
frac <<= (E - 23);
}else{
frac >>= (23 - E);
}
if(s)
return ~frac + 1;
return frac;
}
13. floatPower2
题意:对于任何 32 位整数 x,返回表达式 2.0^x 的位级等效项。
题解:我们可以由小到大判断:
- (非规格化f为0的情况)E最小为-126,M最小为
2^-23,故x<-149,这个数太小,return 0 - (非规格化f不为0的情况)此时需要填充f,expr全为0,E = -126,若x < -126,剩余部分需f补充,即1 << (23 + (x + 126))
- (规格化的情况)求出expr即可,E = expr - bias,则expr = E + bias,E就是参数x,之后把expr放到对应位置即可
- (NaN和无穷大)expr全部填充为1
/*
* 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 < -149){
return 0;
}else if(x < -126){
// E = x
// E = 1 - 127 = -126
int shift = 23 + (x + 126);
return 1 << shift;
}else if(x <= 127){
//x = expr - bias
int expr = x + 127;
return expr << 23;
}else{
return (0xFF) << 23;
}
}
1793

被折叠的 条评论
为什么被折叠?



