csapp lab1 datalab
主要考验位操作的相关技巧。熟练了就不难。
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) {
}
x^y=(x&~y)|(~x&y),m|n=~(~m&~n)
int bitXor(int x, int y) {
return ~(~(x&~y)&~(~x&y));
}
2. tmin
略过
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) {
}
考虑4位,x=0111,x+1=1000,有2x+1=1111,证明k=1111:!(~k)
但x=1111时也成立,需排除掉。x+1!=0可以排除掉
int isTmax(int x) {
int m=x+1;
return !!m&!(~(m+x));
}
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) {
}
构造a=0xAAAAAAAA,(a&x)|(a>>1)判断是否为0xFFFFFFFF
int allOddBits(int x) {
int a=0xAA;
a=a|(a<<8);
a=a|(a<<16);
int m=x&a;
return !(~(m|(m>>1)));
}
5. negate
考察定义
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+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) {
}
x-0x30是否大于等于0,0x39-x是否大于等于0
int isAsciiDigit(int x) {
int Tmin=1<<31;
int a=x+~0x30+1;
int b=0x3A+~x;
return !(a&Tmin)&!(b&Tmin);
}
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) {
}
(y&m)+(z&~m),当x为true时,m=0xffff,当x为false时,m=0
int conditional(int x, int y, int z) {
int m=(!x)+~0;
return (y&m)+(z&~m);
}
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) {
}
符号相同,比差值符号。符号不同,看y符号。
注意:不能简单看差值符号!正-负有可能会正溢出,导致符号为负
int isLessOrEqual(int x, int y) {
int Tmin=1<<31;
int diff=!!((x^y)&Tmin); //sign diff,1; else, 0
int a=!(y&Tmin);
int b=!((y+~x+1)&Tmin);
return (diff&a)|(!diff&b);
}
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) {
}
0的特殊性:相反数的符号和自己相同(唯一特例:Tmin,需要排除)
int logicalNeg(int x) {
int a=(x>>31)+1;
int b=(((~x+1)^x)>>31)+1;
return a&b;
}
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) {
}
首先,如果x为负,将x取反。
利用二分法,32位中看高16位是否有1,如果有,则x右移16位。然后看x的16位中的高8位是否有1,...以此类推即可。
int howManyBits(int x) {
int b16,b8,b4,b2,b1;
x=x^(x>>31); // sign=0: x=x; sign=1: x=~x
b16=!!(x>>16)<<4; // high 16 bits has 1: 16; else: 0
x>>=b16;
b8=!!(x>>8)<<3;
x>>=b8;
b4=!!(x>>4)<<2;
x>>=b4;
b2=!!(x>>2)<<1;
x>>=b2;
b1=!!(x>>1);
x>>=b1;
return b16+b8+b4+b2+b1+(!!x)+1; //1 for sign bit
}
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) {
}
当阶数exp=0时,需要将frac右移一位。注意:可能会进位到阶数!
当阶数exp!=0且不全为1时,表示规格化的数,需要给exp+1
当阶数exp全为1时,表示无穷或NaN。
unsigned floatScale2(unsigned uf) {
unsigned exp=0x7f800000; // exp all 1
if((uf&exp)==0){ // exp=0, frac right shift
return ((uf&0x007fffff)<<1)|(uf&0x80000000);
}else if((uf&exp)!=exp){ // exp not 0 or all 1, exp++
return uf+0x00800000;
}else{ // exp all 1, uf=NaN or infinity
return uf;
}
}
12. floatFloat2Int
/*
* 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) {
}
规格化的值:在阶码最后一位设为1,高位设为0,并根据阶码大小和23的差值,左移或者右移。
非规格化的值:当阶码全为1,或者E>=32(此时对应int值已经超过INT_MAX了)
int floatFloat2Int(unsigned uf) {
int e=(uf>>23)&0xff;
int E=e-127;
int exp=0x7f800000;
int s=(uf>>31)&0x1;
unsigned INF=1<<31;
if((uf&exp)==exp||E>=32){
return INF;
}
if(E<0){
return 0;
}
// uf exp last bit sets 1, high bits set 0
uf|=0x00800000;
uf&=0x00ffffff;
if(E>=23){
uf<<=(E-23);
}else{
uf>>=(23-E);
}
if(s){
uf=~uf+1;
}
return uf;
}
13. floatPower2
/*
* 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) {
}
尾数全为0,关键看阶码。
x=1时,,要左移22位,23-(e-127)=22,e=128
得到关系:e=x+127
当x+127为负时,由于e是无符号数,不能为负,则返回0。
由于E=e-127的范围是[-126,127],x的范围也是[-126,127]
unsigned floatPower2(int x) {
int e=x+127;
if(e<0){
return 0;
}
if(x>127){
return 0x7f800000u;
}
return e<<23;
}
分类:
csapp lab
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!