内容是整数与浮点数的位级操作。
/*
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8
* Rating: 1
*/
int bitAnd(int x, int y) {
return ~(~x | ~y); }
/*
* getByte - Extract byte n from word x
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
int tmp = x >> ((n) << 3);
tmp = tmp & 0xFF;
return tmp;
}
1<<(y+1)
写为两个1<是为了防止n=0时的溢出。
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
int y = 32 + (~n);//31-n
return (x >> n) & ((1 << y) + (~0) + (1 << y));
}
x&(x-1)
,在网上又看了一些其他的做法。/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
int _mask1 = (0x55)|(0x55<<8);
int _mask2 = (0x33)|(0x33<<8);
int _mask3 = (0x0f)|(0x0f<<8);
int mask1 = _mask1|(_mask1<<16);
int mask2 = _mask2|(_mask2<<16);
int mask3 = _mask3|(_mask3<<16);
int mask4 = (0xff)|(0xff<<16);
int mask5 = (0xff)|(0xff<<8);
int ans = (x & mask1) + ((x>>1) & mask1);
ans = (ans & mask2) + ((ans>>2) & mask2);
ans = (ans & mask3) + ((ans>>4) & mask3);
ans = (ans & mask4) + ((ans>>8) & mask4);
ans = (ans & mask5) + ((ans>>16) & mask5);
return ans;
}
~x+1
。/*
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int bang(int x) {
return ((x | ~x + 1) >> 31) + 1; }
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return 1 << 31; }
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
x >>= ~(~n + 1);
return (!x | !(x + 1));
}
(1<。((x>>31)&1< 只有当x为负数的时候才有有效值。
/*
* divpwr2 - Compute x/(2^n), for 0 <= n <= 30
* Round toward zero
* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int divpwr2(int x, int n) {
return (x+(((x>>31)&1)<<n)+(~0)+(!((x>>31)&1)))>>n;
}
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1;
}
/*
* isPositive - return 1 if x > 0, return 0 otherwise
* Example: isPositive(-1) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 3
*/
int isPositive(int x) {
return !((x >> 31 & 1) | !x); }
y-x
的正负,但是要注意溢出的问题。如果是异号很容易溢出。因此要特判而不是直接作差。/*
* 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 signx = (x >> 31) & 1;
int signy = (y >> 31) & 1;
int isSameSign = !(signx ^ signy);
int p = !(((~x) + 1 + y) >> 31);
int ans = (isSameSign & p) | ((!isSameSign) & signx);
return ans;
}
/*
* ilog2 - return floor(log base 2 of x), where x > 0
* Example: ilog2(16) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
int ilog2(int x) {
int ans = 0;
ans = ans + ((!!(x>>(16 + ans)))<<4);
ans = ans + ((!!(x>>(8 + ans)))<<3);
ans = ans + ((!!(x>>(4 + ans)))<<2);
ans = ans + ((!!(x>>(2 + ans)))<<1);
ans = ans + ((!!(x>>(1 + ans)))<<0);
return ans;
}
/*
* float_neg - Return bit-level equivalent of expression -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 representations of
* single-precision floating point values.
* When argument is NaN, return argument.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 10
* Rating: 2
*/
unsigned float_neg(unsigned uf) {
unsigned tmp = uf&(0x7fffffff);
unsigned result = uf^(0x80000000);
if(tmp>0x7f800000) result=uf;
return result;
}
(f > 128) || ((f == 128) && (tail & 1))
来表示(f是被截掉的部分)。/*
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, whilef
* Max ops: 30
* Rating: 4
*/
unsigned float_i2f(int x) {
unsigned ans;
int tmpx = x;
int f = 0;
int delta = 0;
int tail = 0;
int E = 0;
//特殊情况
if (x == 0)
return x;
if (x == 0x80000000)
return 0xcf000000;
//符号位
ans = x & 0x80000000;
//取绝对值
if (ans)
tmpx = -x;
//计算移位数
while ((tmpx >> E))
E++;
E = E - 1;
//移位
tmpx = tmpx << (31 - E);
//尾数截掉八位
tail = (tmpx >> 8) & 0x007FFFFF;
//被截掉部分
f = tmpx & 0xff;
//向上舍入的情况
delta = (f > 128) || ((f == 128) && (tail & 1));
tail += delta;
//阶码计算
E = E + 127;
//溢出判断
if (tail >> 23) {
tail = tail & 0x007FFFFF;
E += 1;
}
ans = ans | E << 23 | tail;
return ans;
}
/*
* float_twice - 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 float_twice(unsigned uf) {
unsigned sign = uf >> 31;
unsigned exp = uf >> 23 & 0xFF;
unsigned frac = uf & 0x7FFFFF;
if (exp == 0 && frac < 0x7FFFFF)
frac <<= 1;
else if (exp == 0 && frac == 0x7FFFFF) {
exp += 1;
frac = 0x7FFFFE;
} //非规格化
else if (exp == 0xFE) {
exp = 0xFF;
frac = 0;
} else if (exp == 0xFF)
return uf;
else
exp += 1;
return (sign << 31) | (exp << 23) | frac;
}
运行结果:
总结:
自己觉得最难的是bitCount,ilog2,float_i2f和float_twice。感觉自己只掌握了很基础的一部分知识,对于灵活使用并不熟练。浮点数的边界情况考虑,运算的溢出情况,取整的知识还有别人的巧妙思考,都是可以从中学习的。