修改bits.c
,使其满足btest
的测试,代码规范./dlc bits.c
测试
思路
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
// 两个1的位置是0,否则是1
int a = ~(x & y);
// 两个0的位置是0,否则是1
int b = ~(~x & ~y);
// 因此将a和b按位&之后,两个1或者两个0的位置都是0,其他位置是1
return a & b;
}
思路
/*
* 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) {
// 0xffffffff,这一步不能用异或
int a = x + x + 1;
// 0x00000000,如果b为0,那么b要么是0x3fffffff,要么是0xffffffff
int b = ~a;
// 排除x为0xffffffff,如果x是0xffffffff,那么c就是1,否则c就是0
int c = !(x + 1);
// 只有b和c都是0,才返回1
return !(b | c);
}
思路
/*
* 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) {
// 构造出奇数位均为1的数
int a = (0xaa << 24) + (0xaa << 16) + (0xaa << 8) + 0xaa;
// 将a看做掩码,取出x中所有奇数位
int b = x & a;
// 判断a和b是否相同,只有当a和b相同,异或才为0,那么取!后才为1
return !(a ^ b);
}
思路
/*
* 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: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 3
*/
int isAsciiDigit(int x) {
// 0x 0011 0000
// 0x 0011 1001
// 首先,右移4位之后,应该是0x3,即a=1
int a = !((x >> 4) ^ (0x3));
// 低4位,要么第4位为0,要么就只能是1001或者1000
// b为1,代表第4位为0
int b = !((x >> 3) & 1);
// c为1,代表为1001或者1000,即第1位和第4位无所谓,但是第2和第3位必须是0
int c = !(x & 0x6);
// printf("-----------------\n%x\n%d\n%d\n%d\n%d\n",x,a,b,c,a&(b|c));
return a & (b | c);
}
思路
/*
* 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不为0,则得到一个全1的数,如果x为0,则得到一个全0的数
// 如果x为0,则得到0,如果x非0,则得到1
int a = !!x;
// 如果a为0,则b为0,如果a为1,则b为-1,即全1
int b = ~a + 1;
// c和d一定有一个为0
int c = b & y;
int d = ~b & z;
return c | d;
}
思路
/*
* 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) {
// 如果符号不同,则正数更大,如果符号相同,则看差值,还要特判一下x是否和y相同
int x_flag = x >> 31 & 1;
int y_flag = y >> 31 & 1;
// 如果flag_not_same为1,则代表符号不同,如果为0,则代表符号相同
int flag_not_same = x_flag ^ y_flag;
// 还要结合差值的正负来看,x-y,即x+(y的补码)
int y_ = ~y + 1;
int sub_flag = (x + y_) >> 31 & 1;
// 如果符号不同并且x为负,即a=1,即x_flag=1,并且flag_not_same=1,
int a = flag_not_same & x_flag;
// 如果符号相同,并且差值为负,即b=1,即flag_same=0,sub_flag=1;
int b = !(flag_not_same | (!sub_flag));
// 如果两个数相同,则c为1,否则c为0
int c = !(x ^ y);
return a | b | c;
}
思路
/*
* 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) {
// 先得到最大的32位有符号数
int T_max = ~(1 << 31);
// 得到x的符号
int x_sign = x >> 31 & 1;
// 将x和T_max相加,除了0,其他的数加上去之后一定是一个负数
int a = x + T_max;
int a_sign = a >> 31 & 1;
// 只有当x和a的sign都是0时,才返回1,否则返回0
return (x_sign ^ 1) & (a_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) {
// 如果是正数,那么直接求x的最高位1,如果是负数,则是要求最高位的0
// 假设这个最高位为第x位,则答案案为x+1位,因为正数需要加上符号0,负数需要加上符号1
// 对于负数,先预处理,将所有的1变成0,所有的0变成1
// 如果x为正数,则help为0,如果x为负数,则help为0xffffffff
int ans = 0;
int help = x >> 31;
// 通过help将x的1变成0,0变成1。若help为0,则x不变,若help为全1,则完成转换的任务
x = x ^ help;
// 下面就统一为了计算最高位的1所在的位置
// 如果高16位不为0,则has_high_16为1,否则为0
int has_high_16 = !!(x >> 16);
// 如果高16位存在,即has_high_16为1,那么说明低16位肯定跑不掉了,正好就是has_high_16<<4
// 如果高16位不存在,has_high_16为0,低16位就不一定都要,此时左移4位正好是0
int add_bits = has_high_16 << 4;
ans += add_bits;
// 又是一个很巧妙的操作,如果add_bits不为0,说明低16位肯定是需要的,那么就不用管低16位,直接移位
// 如果add__bits为0,说明高16位肯定不需要,低16位可能需要,那么此时右移0位,接下来正常处理低16位
x >>= add_bits;
int has_high_8 = !!(x >> 8);
add_bits = has_high_8 << 3;
ans += add_bits;
x >>= add_bits;
int has_high_4 = !!(x >> 4);
add_bits = has_high_4 << 2;
ans += add_bits;
x >>= add_bits;
int has_high_2 = !!(x >> 2);
add_bits = has_high_2 << 1;
ans += add_bits;
x >>= add_bits;
int has_high_1 = !!(x >> 1);
add_bits = has_high_1 << 0;
ans += add_bits;
x >>= add_bits;
// x可能现在是1
ans += x;
return ans + 1;
}
思路
/*
* 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) {
// 分别取出符号,指数,以及有效数位,
// 其中有效的取出比较tricky,是对sign和e的对应位置进行异或,即将高9位都置为0,剩下的就是有效数位了
unsigned sign = (uf >> 31) & 1;
unsigned e = (uf >> 23) & 0xff;
unsigned f = uf ^ (sign << 31) ^ (e << 23);
// 如果uf为NaN等特殊值,即指数为全1,直接返回这个特殊值本身
if (!(e ^ 0xff)) {
return uf;
}
// 如果uf为非规格化的数,即指数为0,直接将f*2即可
// 这里感觉有点问题,如果这个非规格数*2后达到了规格数的范围了,是不是要额外处理?
if (!e) {
return (sign << 31) | (f << 1);
}
// 如果uf为规格化的数
return (sign << 31) | ((e + 1) << 23) | (f);
}
思路
/*
* 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) {
// 分别取出符号,指数,以及有效数位,
// 其中有效位的取出比较tricky,是对sign和e的对应位置进行异或,即将高9位都置为0,剩下的就是有效数位了
unsigned sign = (uf >> 31) & 1;
unsigned e = (uf >> 23) & 0xff;
unsigned f = uf ^ (sign << 31) ^ (e << 23);
// 如果指数大于等于31了,因为要返回的值是int类型,1<<31位直接爆int了,所以返回0x80000000u
int E = e - 127;
if (E >= 31) {
return 0x80000000;
}
// 如果指数小于0了,那么肯定是返回0,因为需要对小数部分除2,那么对int来说,就是0
if (E < 0) {
return 0;
}
// 真正的小数部分,是有一个隐藏的1在最前面的,这里不用考虑非规格化数,因为它已经在前面的E<0里给淘汰了
int frac = f | 0x800000;
// 这个小数部分是用整数来表示的,即默认左移了23位,那么当前的移位应该减去23
int real_f = (E > 23) ? (frac << (E - 23)) : (frac >> (23 - E));
return sign ? -real_f : real_f;
}
思路
/*
* 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) {
// 得到阶码
int e = x + 127;
// 非规格数,直接返回0
if (e <= 0) {
return 0;
}
// 无穷
if (e >= 0xff) {
return 0x7f800000;
}
// 规格数,符号位0,小数部分也是0
return e << 23;
}