位运算
一、概述
运算符 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两位都为1时,结果为1 |
| | 或 | 两位都为0时,结果为0 |
^ | 异或 | 两位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
>> | 右移 | 各位右移若干位,对于无符号数高位补0,有符号数各编译器处理方法不一,或补符号位(算术右移),或补0(逻辑右移) |
<< | 左移 | 各位全部左移若干位,高位丢弃,低位补0 |
运算优先级:~
> >>, <<
> &
> ^
> |
二、技巧
1、与
1)清零
int n = 10;
n &= 0;
2)奇偶判断
int n = 10;
if((n & 1) == 0)
{
std::cout << "偶数\n";
}
else
{
std::cout << "奇数\n";
}
3)取位
例:现有十进制数174(二进制为1010 1110),若想得到其后四位,则将它与第4位为1,其他位为0的数(即二进制数0000 1111,十进制数15)进行与运算,结果为十进制数14(二进制为0000 1110)。
int n = 174;
n &= 15; // n = 14
2、或
1)将指定位设为1
例:现有十进制数174(二进制为1010 1110),若想将其低4位设为1,则将其与二进制数0000 1111(十进制数15)进行或运算,结果为十进制数175(二进制为1010 1111),若想将某位设为1,则或某个数,这个数这一位为1其他都为0。
int n = 174;
n |= 15; // n = 175
n = 174;
n |= 16; // n = 190(二进制:1011 1110)
PS:不同于与运算,我们很少用或运算进行任意位赋值。通常来讲,我们只使用n | 1
把 n 的最后一位强行变成 1,其实质意义是把原数加一。或者使用a | 1 - 1
再把它变为 0,这个技巧通常用于把 n 变成 n 最接近的偶数。
3、异或
异或符合以下几条性质:
① 交换律
② 结合律 (a ^ b) ^ c = a ^ (b ^ c)
③ 对于任何数 n,都有n ^ n = 0
和n ^ 0 = n
④ 自反性 a ^ b ^ b = a ^ 0 = a
1)翻转指定位
例:现有十进制数174(二进制为1010 1110),若想翻转其低4位,则将其与二进制数0000 1111(十进制数15)进行异或运算(低4位为1,其他都为0),结果为十进制数161(二进制为1010 0001);若想翻转某一位,则异或一个数,这个数这一位为1其他都为0。
int n = 174;
n ^= 15; // n = 161
n = 174;
n ^= 16; // n = 190(二进制:1011 1110)
4、取反
1)与 & 运算配合使一个数最低位为0
int n = 175; // 二进制:1010 1111
n = (n & ~ 1); // n = 174
5、右移
1)除法优化
a >> b
本质为a / pow(2, b)
int a = 16;
int b = 1;
a >>= b; // a = 16 / 2 = 8
a = 16;
b = 2;
a >>= b; // a = 16 / (2 * 2) = 4
6、左移
1)乘法优化
a << b
本质为a * pow(2, b)
int a = 2;
int b = 1;
a <<= b; // a = 2 * 2 = 4
a = 2;
b = 2;
a <<= b; // a = 2 * (2 * 2) = 8
三、拓展
1、计算一个数二进制中1的个数
// 方法一
int CountOf1(int num)
{
int count = 0;
unsigned int flag = 1;
while(flag)
{
if(num & flag)
{
++count;
}
flag = flag << 1;
}
return count;
}
// 方法二
int CountOf1(int num)
{
int count = 0;
while(num)
{
num &= num - 1;
++count;
}
return count;
}
2、判断一个数是否为2的n次方
bool Is2Power(int num)
{
num &= num - 1;
if(num)
{
return false;
}
return true;
}
3、获得最大int值
int GetMaxInt()
{
return ((unsigned int)-1) >> 1;
}
4、获得最小int值
int GetMinInt()
{
return 1 << 31;
}
5、交换两个数(不使用临时变量)
void Swap(int &a, int &b)
{
a ^= b;
b ^= a;
a ^= b;
}
6、求一个数的绝对值
int Abs(int n)
{
return (n ^ n >> 31) - (n >> 31);
}