位运算相关
位运算概览
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 有0为0 |
| | 或 | 有1为1 |
^ | 异或 | 相同为0 相异为1 |
~ | 取反 | 1变 0 0变1 |
<< | 左移 | 各二进制位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进制位全部右移若干位,对无符号数,高位补0, 有符号数,各编译器处理方法不一样,有的补符号位(算数右移),有的补0(逻辑右移) |
常见位运算解决的问题
1.每左右移动一位相当于乘除2;
2.交换两个数
//用于交换两个数,不需要临时变量,普通操作虽然也可以,但是没有位运算效率高
//普通操作
void swap(int &a, int &b) {
a = a + b;
b = a - b;
a = a - b;
}
//位与操作
void swap(int &a, int &b) {
a ^= b;
b ^= a;
a ^= b;
}
3.判断奇数偶数
//只要根据数的最后一位是 0 还是 1 来决定即可,为 0 就是偶数,为 1 就是奇数。
if(0 == (a & 1)) {
//偶数
}
4.交换符号
int reversal(int a) {
return ~a + 1;
}
5.求绝对值
//整数的绝对值是其本身,负数的绝对值正好可以对其进行取反加一求得,即我们首先判断其符号位(整数右移 31 位得到 0,负数右移 31 位得到 -1,即 0xffffffff),然后根据符号进行相应的操作
int abs(int a) {
int i = a >> 31;
return i == 0 ? a : (~a + 1);
}
6.高低位交换
/**给定一个 16 位的无符号整数,将其高 8 位与低 8 位进行交换,求出交换后的值,如:34520的二进制表示:
10000110 11011000
将其高8位与低8位进行交换,得到一个新的二进制数:
11011000 10000110
其十进制为55430
从上面移位操作我们可以知道,只要将无符号数 a>>8 即可得到其高 8 位移到低 8 位,高位补 0;将 a<<8 即可将 低 8 位移到高 8 位,低 8 位补 0,然后将 a>>8 和 a<<8 进行或操作既可求得交换后的结果。
*/
unsigned short a = 34520;
a = (a >> 8) | (a << 8);
7.二进制逆序
/**
数34520的二进制表示:
10000110 11011000
逆序后则为:
00011011 01100001
它的十进制为7009
*/