Datalab
本文是学习csapp第二章做的对应的Lab(DataLab),思路主要是来源于b站郭郭,个人认为讲的思路是很详细的,有兴趣的同学可以去b站看一下讲解
#endif
//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) {
//(a|b) & (~a|~b) rt
return ~((~x)&(~y)) & (~(x & y));
}
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
//最小的(补码对应的)真值
//补码:100000...00
//真值:-10000..000 ->32位
return 1 << 31;
}
//2
/*
* 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) {
//是否是补码的最大值
//01111111..1111,判断是否相同
/*
* 原来不让用<<符号的鸭, 我傻了
x = ~x;
int a = 1 << 31;
x ^= a;
return (!x);
*/
//如果说不用设置新的变量能不能行
//就要特判1111111..11
return (!(~(x + 1) ^ (x))) & (!!(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) {
//所有的都至少含有AAAAAAAA
int A = 0xA;
int AA = A | (A << 4); //用 | 将剩余的进行填充
int AAAA = AA | (AA << 8);
int A8 = (AAAA | AAAA << 16);
//将所有的偶数项目全部清除掉
x = (x & A8);
//如果所有奇数位置全部都是1,可以用异或与AAAA
return !(x ^ A8);
return 2;
}
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
//所有的int都是用补码表示的
//负数对应的二进制需要转换成为真值
//1101 -> -3 取反:2
//0010 -> 2 取反:-3
return ~x + 1; //按位取反 + 1
}
//3
/*
* 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) {
//1. 000000..11xxxx
int cond1 = x >> 6;
cond1 = !cond1;
//2. 判断是否是11
int cond2 = x >> 4;
cond2 = !(cond2 ^ 0b11);
//3. 最后四位是否小于10
int cond3 = x & (0xF); //拿到后四位
cond3 = cond3 + (~0xa + 1); //cond3 - A
cond3 = cond3 >> 31; //取到符号位,判断是否是1 -> 负号
return cond1 & cond2 & cond3;
}
/*
* 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) {
//实现三目运算符号
//挺难的,根据掩码将两个运算符号同时出现
//x | y
//思考:什么并或者交0 1 自身不变
// x = !!x; //1或者是0
//不是1 而是 111111111
int mask = ((!!x) << 31) >> 31;
//0 -> 00000000
//1 -> 11111111
return (mask & y) | ((~mask) & 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) {
//1、符号相同就判断y-x的符号
//2、符号不同 如果x小于0就是的了
int result = y + (~x + 1);
int signX = (x >> 31) & 1;
int signY = (y >> 31) & 1;
int sign = (signX ^ signY); //如果同号就为0
result = (result >> 31) & 1;
return ((!sign) & !(result) ) | (sign & signX );
//不同号,y-x >= 0 同号且x为负
}
//4
/*
* 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) {
//很巧妙的方法
// a = 0111
// -a = 1001
//如果是0 的话 正负x的符号位都是0
//否则正负x的符号位是相反的
/*int negX = (~x + 1);
int sign = (negX | x) >> 31; //算术右移,左边31个全部用1填充
//如果是0 sign = 00000000..00 ->真值是0
//如果是1 sign = 11111111..11 ->真值是-1
return sign + 1;
*/
//如果是0的话,正负号的符号位都是0
//如果是1的话,正负号的符号位是相反的
int negX = ~x + 1;
int sign = (negX | x) >> 31;
//算术右移,
return sign + 1;
}
/* 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) {
return 0;
//不行,真的不会饿啦,自己去b站看看吧 :(
}
//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) {
//if is leage
//get sign expr frac
unsigned s = (uf >> 31) & (0x1);
unsigned expr = (uf >> 23) & (0xFF);
unsigned frac = (uf & 0x7FFFFF); //23bits
//if uf == 0
if (expr == 0 && frac == 0)
return uf;
//inif or NAN
if (expr == 0xFF)
return uf;
//denomalize
if (expr == 0) {
frac <<= 1;
return (s << 31) | frac; //expr == 0
}
//nomalize
//expr +1 -> uf * 2
expr++;
return (s << 31) | (expr << 23) | (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) {
unsigned s = (uf >> 31) & (0x1); //符号位
unsigned expr = (uf >> 23) & (0xFF);
unsigned frac = (uf & 0x7FFFFF); //23bits
if (expr == 0 && frac == 0)
return 0;
//inf or NAN
if (expr == 0xFF) {
return 1 << 31; //return 0x80000000
}
//Denomalize
//E -> 1 - Bias = 1 - 127 = -126
//two small
if (expr == 0) {
return 0;
}
//normalize
int E = expr - 127; //指数
//加上前面的隐含的1(leading bit)
frac |= (1 << 23);
//判断E过大或者过小的情况
if (E > 31) {
return 1 << 31; //爆int了
}else if (E < 0){
return 0; //E是1.xxxxx 除以二后变为0了
}
//将指数部分乘到尾数上面(判断尾数左移或者右移几位)
if (E >= 23) {
frac <<= (E -23);
}else {
frac >>= (23 -E);
}
//最后判断符号位
if (s) return ~frac + 1; //按位取反加一
return frac;
}
/*
* 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) {
//表示成为浮点数
//denomalize E恒等于-126 frac 属于 [2^-23, 1)
/*
*最终denomarlize 的范围就是2 ^ -149 到 2 ^(-126) * (...) -> frac全部为1
*
* normarlize
* 指数的范围是 -126 到 127
*
*
* 乘上frac 范围是 2 ^ -126
* 最大数接近于 2 * 2 ^ 127
*
*
* */
//X就是指数,尾数是1,符号数是0
if ( x < -149) {
return 0; //太小了
}else if ( x < -126 ) {
//denomarisze
//指数X = 1 - 127 = -126
int number = 23 + (x + 126);
return 1 << number;
}else if (x <= 127) {
//指数X = expr - bias
//我们求expr
int expr = x + 127;
return expr << 23;
}else { //inf
return (0xFF) << 23;
}
}