目录
1.bitOr
2.evenBits
3.isTmin
4.allEvenBits
5.anyEvenBit
6.fitsBits
7.float_neg
8.isAsciiDigit
9.isLess
10.multFiveEighths
11.replaceByte
12.bitParity
13.float_half
14.ilog2
15.sm2tc
使用运算符个数:4
题目:用~和&实现|
解析:
按位取反运算符的逻辑:原数的补码按位取反,取按位取反后的数的反码,再取补码,得到的即为按位取反后的数
可知,~x = -(x+1)
德摩根定律:~(x&y) = (~x)|(~y) ~(x|y) = (~x)&(~y)
则x|y = ~(~(x|y)) = ~((~x)&(~y))
/*
* bitOr - x|y using only ~ and &
* Example: bitOr(6, 5) = 7
* Legal ops: ~ &
* Max ops: 8
* Rating: 1
*/
int bitOr(int x, int y) {
return ~((~x) & (~y));
}
使用运算符个数:4
题目:返回一个32位的二进制数,其偶数位均为1
解析:
需要注意的是,最低位为0位,即返回的数为010101……0101
题目要求取的数大小不能超过255,则先取a = 0x55,一个8位二进制数
将a左移8位,后面补8个0,与0x55按位或(有1结果为1),得到16位0101……的二进制数
同理,左移16位按位或本身,得到题目要求的32位数
/*
* evenBits - return word with all even-numbered bits set to 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int evenBits(void) {
int a = 0x55 << 8 | 0x55;
return ((a << 16) | a);
}
使用运算符个数:6
题目:如果x是32位二进制能表示的最小数,返回1,否则返回0
解析:
由题可知,如果x是最小数,那么x = 10000……000,则x满足x == ~x+1
判断两数相等使用异或操作(不同才为1)
同时,需要排除同样满足条件的0x00000000
/*
* isTmin - returns 1 if x is the minimum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/
int isTmin(int x) {
return !((x ^ (~x + 1)) | (!x));
}
其他方法:4
int evenBits(void) {
int x = 85;
x = x | (x << 8);
x = x | (x << 16);
return x;
}
使用运算符个数:7
题目:如果x偶数位全为1,返回1
解析:
取y = 0xAA,即10101010,同第二题操作,先按位或左移8位,再按位或左移16位,得到32位的101010……1010
y|x,如果得到32位全1,则x的偶数位全1,~(x|y)为0,!~(x|y)为1
/*
* allEvenBits - return 1 if all even-numbered bits in word set to 1
* Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
int allEvenBits(int x) {
int y = 0xAA;
y = y | y << 8;
y = y | y << 16;
return !~(x | y);
}
使用运算符个数:7
题目:如果x有任何一位偶数位为1,返回1
解析:
构造y = 0x55555555,即010101……0101
x&y,如果x有偶数位为1,结果不为0,如果x偶数位全部为0,结果为0
!!(x&y),两次!,为了得到单独的1或0
/*
* anyEvenBit - return 1 if any even-numbered bit in word set to 1
* Examples anyEvenBit(0xA) = 0, anyEvenBit(0xE) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
int anyEvenBit(int x) {
int y = 0x55 | 0x55 << 8;
y = y | y << 16;
return !!(x & y);
}
使用运算符个数:7
题目:如果x可以用n位二进制数表示,返回1,否则返回0
解析:
~0为0xFFFFFFFF,值为-1,a = n+(~0)指a = n-1
b = x>>a,将x右移n-1位,正数移后值为0,负数为-1
(!b|(!(b+1))),判断b是否全为0或全为1,如果全为0或全为1,返回1
/*
* 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) {
int a = n + (~0);
int b = x >> a;
return (!b | !(b + 1));
}
使用运算符个数:3
题目:返回uf的负数,如果uf是NaN,返回其本身
解析:
单精度浮点数用IEEE754存储,即将符号位取反就得到uf的负数
NaN用IEEE756表示时,符号位为0或1,阶码全为1,尾数非零
如果uf&0x7FFFFFFF>0x7F800000,uf为NaN,返回其本身
其他数,uf^0x80000000,将符号位取反后返回
/*
* 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) {
if((uf & 0x7fffffff) > 0x7f800000)
return uf;
return uf ^ 0x80000000;
}
使用运算符个数:12
题目:如果x的值在0x30到0x39之间,返回1
解析:
判断x-0x30和0x39-x的正负,减法用-x = (~x)+1实现
c = 1<<31,得到32位二进制最小数,只有最高位是1
(!(a&c))&(!(b&c)),如果a和b均为整数,&c得0,!得1,即只有a、b均为整数返回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) {
int a = x + (~0x30 + 1);
int b = 0x39 + (~x + 1);
int c = 1 << 31;
return (!(a & c)) & (!(b & c));
}
其他方法:8
int isAsciiDigit(int x) {
return (!((x + ~0x2F) >> 31)) & ((x + ~0x39) >> 31);
}
使用运算符个数:14
题目:如果x 解析: a = ((x&~y)>>31)&1,判断x为负数,y为正数的情况,如果x为负y为正,a = 1 b = ~((x^y)>>31),x和y符号相同时b = 1,否则b = 0 (x+~y+1)>>31,获取x-y的符号位,当两数符号位相同且x-y为负数时,结果为1 其他方法:5 使用运算符个数:6 题目:将x*5/8,并向0舍入 解析: x = x+(x<<2),x<<2为x*4,再加1,即为x*5 x>>3为x/8,对于正数来说满足向0舍入,但对于负数来说,如果移出部分非0,需要给整数部分加1才是向0舍入 将x>>31得到符号位,并且&7(7的二进制位000……0111) 如果x是正数,结果为0,x直接右移3位 如果x是负数,结果为x+7,相当于给高位进1,之后再右移3位 使用运算符个数:7 题目:将x的第n个字节用c代替 解析: n<<3,即n*8(一个字节八个比特位),a = 0xFF<<(n<<3),将第n个字节变为全1 c <<= (n<<3),将c移到第n个字节的位置 x&(~a),将x的第n个字节清零,后按位或c(有1结果为1) 其他方法: 6 使用运算符个数:11 题目:如果x含有奇数个0,返回1 解析: x ^= x>>16,将x的高16位和低16位异或(不同才为1),即如果两位相同,是偶数个,消掉 同理,直到x剩下1位,如果有奇数个0,x的最低位 != 0,如果是偶数个0,x的最低位 = 0 返回x&1(只取x最低位) 使用运算符个数:30 题目:返回0.5*uf 解析: 对于0,无穷大和NaN,直接返回其本身 对于非规格化数,尾数右移1位,需要考虑舍入问题 对于规格化数,阶码-1,如果-1后为0,变成非规格化数,尾数最高位需要补1,最低位需要移出 尾数+1,向偶数舍入 其他方法:7 使用运算符个数:24 题目:返回以2为底x的对数,向下取整 解析: 若x = 00010000,结果为4;若x = 00010001,结果为4.1699……,向下取整后为4 问题转换为求x最高1位的位数(位数是从0到31) 用一个5位二进制数b4b3b2b1b0来表示 如果高16位有1,b4 = 1,如果高16位的高8位有1,b3 = 1,如果高16位的高8位的高4位有1,b2 = 1,以此类推 使用运算符个数:5 题目:将原码转换为补码形式 解析: a = (x>>31),取x的符号位 x^a,若x为正数,结果不变,若x为负数,结果为x取反/*
* isLess - if x < y then return 1, else return 0
* Example: isLess(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLess(int x, int y) {
int a = ((x & ~y) >> 31) & 1;
int b = ~((x ^ y) >> 31);
return a | ((b & ((x + ~y + 1) >> 31)) & 1);
}
int isLess(int x, int y) {
int not_y = ~y;
long long lltemp=x;
return 1+((y+~lltemp)>>63);
}
10.multFiveEighths
/*
* multFiveEighths - multiplies by 5/8 rounding toward 0.
* Should exactly duplicate effect of C expression (x*5/8),
* including overflow behavior.
* Examples: multFiveEighths(77) = 48
* multFiveEighths(-22) = -13
* multFiveEighths(1073741824) = 13421728 (overflow)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 3
*/
int multFiveEighths(int x) {
x = x + (x << 2);
return (x + (x >> 31 & 7)) >> 3;
}
11.replaceByte
/*
* replaceByte(x,n,c) - Replace byte n in x with c
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
* You can assume 0 <= n <= 3 and 0 <= c <= 255
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 10
* Rating: 3
*/
int replaceByte(int x, int n, int c) {
int a = 0xff << (n << 3);
c <<= (n << 3);
return (x &(~a)) | c;
}
int replaceByte(int x, int n, int c) {
int n_dis = n << 3;
int clear_mask = 0xFF << n_dis;
int new_mask = c << n_dis;
return (x & ~clear_mask) | new_mask;
}
12.bitParity
/*
* bitParity - returns 1 if x contains an odd number of 0's
* Examples: bitParity(5) = 0, bitParity(7) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
int bitParity(int x) {
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return x & 1;
}
13.float_half
/*
* float_half - Return bit-level equivalent of expression 0.5*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_half(unsigned uf) {
int a=0xff<<23;
int b=!((uf&3)^3);
int sign=uf&(0x80<<24);
int exp=uf&a;
int frac=(uf&((((0xff<<8)+0xff)<<7)+0x7f));
if(exp==a)
return uf;
if(exp==(0x80<<16))
return sign|(b+((uf&(~(0x80<<24)))>>1));
if(exp==0x0)
return sign|((frac>>1)+b);
return (((exp>>23)-1)<<23)|sign|frac;
}
unsigned float_half(unsigned uf) {
unsigned half = uf >> 1;
int Sgn = 0;
switch (uf >> 23)
{
case (0x000):case (0x001): break;
case (0x100):case (0x101):{Sgn = 0xc0000000; break;}
case (0x0ff):case (0x1ff): return uf;
default: return uf - 0x800000;
}
return Sgn ^ (half + (uf & half & 1));
}
14.ilog2
/*
* 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 a = 0;
int b = !(x >> 16);
int n = b << 4;
a = n;
x = x << n;
b = !(x >> 24);
n = b << 3;
a = a + n;
x = x << n;
b = !(x >> 28);
n = b << 2;
a = a + n;
x = x << n;
b = !(x >> 30);
n = b << 1;
a = a + n;
x = x << n;
a = a + !(x >> 31);
return 32 + ~a;
}
15.sm2tc