位运算应用口诀
清零取反要用与,某位置一可用或
若要取反和交换,轻轻松松用异或
-
与运算符,&:只有前后两个运算都为1时,结果才为1.
a: 0011 b: 0010 a&b=0010
-
或运算符,|:有1位为1,结果便为1。
a: 0011 b: 0010 a|b=0011
-
异或运算符,^:不相同则为1.
a: 0011 b: 0010 a^b=0001
-
取反运算符,~:1变0,0变1.
a: 0011 ~a= 1100 b: 0010 ~b= 1101
-
移位运算符,<<, >> : 左移乘2,右移除2,如果超出,则舍弃。
a<<5 移前:0000 1111 = 15 移后:1110 0000 = 224
这里列举一些常用的位运算例子。
例一:数字互换
swap(int a,int b)
{
a=a^b;
b=b^a;
a=a^b;
}
例二:求绝对值
abs( int x ) {
int y=x>>31 ;
return(x^y)-y;//也可写作 (x+y)^y
}
例三: X:2,4,8,16转化成二进制是10,100,1000,10000。如果减1则变成01,011,0111,01111。两者做按位与运算,结果如果为0,则X是2的N次方。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
n&=n-1;
if(n==0)
printf("YES!");
else
printf("NO!");
}
例三:统计一个整数的二进制中1的个数。
int CountNumberOfOne(int number)
{
int counter = 0;
while (number)
{
counter++;
number &= number - 1 ;
}
return counter;
}
例四:按位翻转
x=((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1);
x=((x&0xcccccccc)>>2)|((x&0x33333333)<<2);
x=((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4);
x=((x&0xff00ff00)>>8)|((x&0x00ff00ff)<<8);
x=((x&0xffff0000)>>16)|((x&0x0000ffff)<<16);
如果无符号32位整数x=311=(100110111)2,那么经过上述操作后x=3967811584=(11101100100000000000000000000000)2。
例五:枚举恰好含有k个元素的集合
我们假设全集为含有N个元素为 {0,1,2,…,N-1},那么代码段可以写成:
int s = (1 << k) - 1;
while (!(s & 1 << N)) {
// 由当前集合 s 计算下一个合法的集合
int lo = s & -s; // 求出低位的1
int lz = (s + lo) & ~s; // 求出比lo高的0中,最低位的0
s |= lz; // 将lz代表的元素加入集合s
s &= ~(lz - 1); // 将比lz位置低的元素全部清空
s |= (lz / lo / 2) - 1; // 将集合元素个数补足为k个
}
ox开头的代表十六进制,O开头的代表八进制,十进制开头无符号
十六进制:
10——a
11——b
12——c
13——d
14——e
15——f