DataLab -位运算
- 知识储备
首先需要明白基本的一些操作符所代表的含义
按位与(&)、按位或(|)、按位异或(^)、按位加(+)、逻辑取反(!)、按位取反(~)、左移(<<)、右移(>>)
按位与运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 & 0 = 0, 0 & 1 = 0, 1 & 0 = 0, 1& 1 = 1。
按位或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1
按位异或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 ^ 0 = 0, 0 ^1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0
按位加运算将两个运算分量的对应为按位遵照以下规则计算:
0+0=0,0+1=1,1+0=1,1+1=0
左移运算将一个位串信息向左移指定的位,右端空出的位用0补充,每左移1位相当于乘2
右移运算将一个位串信息向右移指定的位,右端移出的位的信息被丢弃,每右移1位,相当于除以2。对无符号数据,右移时,左端空出的位用0补充。对于带符号的数据,如果移位前符号位为0(正数),则左端也是用0补充;如果移位前符号位为1(负数),则左端用0或用1补充,取决于计算机系统。对于负数右移,称用0补充的系统为“逻辑右移”,用1补充的系统为“算术右移”。
按位取反为二进制串对应的1和0进行变换
逻辑取反只有0和非0两种情况
浮点数相关 | 符号位(1) | 阶码位(8) | 尾数(23) |
---|---|---|---|
规格化 | 0 | !=0&!=255 | xxx xxxx xxxx xxxx xxxx xxxx |
非规格化 | x | 0000 0000 | xxx xxxx xxxx xxxx xxxx xxxx |
无穷大 | x | 1111 1111 | 000 0000 0000 0000 0000 0000 |
NaN | x | 1111 1111 | !=0 |
- 题目分析:
/*
* 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);
}
翻:使用~与|表示&符号。
根据布尔运算,a&b=~ (~ a|~b)可解决
/*
* 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) {
return (x >> (n << 3)) & 0xFF;
}
翻:取x字符串从右到左第n位字节(字节为0(低位)-3(高位))
x由16进制串构成,两个数字对应一个字节。由于小端存储,则右边为低位数字。所以首先需要右移8n位,然后使用&0xff取字节。但是此处没有 * 的方式,所以只能先对n进行位运算,使用n<<3代替8n,然后再进行右移,对x>>(n<<3)取最低位字节。
/*
* 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) {
return (x>>n)&~(((1<<31)>>n)<<1);
}
翻:字符串逻辑右移n位,且n属于0-31
本题需要考虑带符号数的正负性。由于正数补0负数补1,所以需要在移位之后对于前面补上的数进行操作使都为0。如果直接左移再右移,由于不清楚具体的位数可能导致吞掉除符号位外多的数。所以可以先让1前移31位(最大范围),然后再右移n-1位(此时第一位为1所以补位为1)。取反后便可以顺利保留原数位置的数为1而将扩展的符号数归0。之后两者相与即可将扩展位置0
/*
* 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,mak2,mask4,mask8,mask16;
mask1 = 0x55 | 0x55 << 8;
mask1 = mask1 | mask1 << 16;
mask2 = 0x33 | 0x33 << 8;
mask2 = mask2 | mask2 << 16;
mask4 = 0x0F | 0x0F << 8;
mask4 = mask4 | mask4 << 16;
mask8