首先膜拜Matrix67大牛~http://www.matrix67.com/blog/
1. 六种位运算符
&:清零特定位,x &= ~(1<<k);
取特定位,x & (1<<k)
|: 置1特定位,x |= 1<<k;
^: 取反特定位,x &= 1<<k;
~: 生成全1掩码,~0
<<
>>:算术右移,-2>>1得到-1,-1>>1仍是-1(java中有单独的逻辑右移>>>)(标准未规定是算术移位,但一般都是)
建议位运算都使用unsigned类型unsigned int x = 1U<<31; (unsigned int 也可简写为unsigned)
移位数会mod W,其中W为数据类型长度,因此<<32等于未移位。
2. 应用
(1)不用temp交换两个数
X ^= y; y ^= x; x ^= y;
可看做y = x^x^y; x = x^(y^y);
而用a = a+b; b = a-b; a = a-b;可能会溢出
(2)求两数的平均值
(x&y) + ((x^y)>>1)
用(x+y)/2可能溢出
(3)判断一个数是否2的幂
!(X & (x-1)) && x
x & (x-1) 消掉x最末尾的1
(4)判断奇偶
X & 1 等于1为奇
(5)判断二进制表示中1的个数的奇偶性,奇偶校验
x ^= x>>1; //每一位表示该位和前一位中1的个数的奇偶性
x ^= x>>2; //每一位表示前4位中1的个数的奇偶性
x ^= x>>4;
x ^= x>>8;
x ^= x>>16; //最后一位表示所有32位中1的个数的奇偶性
bool r = x&1;
r = 1表示有奇数个1
(6)计算二进制表示中1的个数
x = (x & 0x55555555) + ((x>>1) & 0x55555555);//将第1,2位的数字相加放回1,2位
x = (x & 0x33333333) + ((x>>2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x>>8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x>>16) & 0x0000FFFF);
(7)计算二进制表示中前导0的个数 (二分法)
int n=0;
if ((x >> 16) == 0) {n += 16; x <<= 16;}
if ((x >> 24) == 0) {n += 8; x <<= 8;}
if ((x >> 28) == 0) {n += 4; x <<= 4;}
if ((x >> 30) == 0) {n += 2; x <<= 2;}
if ((x >> 31) == 0) {n += 1; x <<= 1;}
n += !(x >> 31); //!0 等于1
看了Matrix67博客的留言才意识到n = n+16; 应该写成n += 16;才像话
3. 位域
struct BS{
unsigned int a:3;
int b:3;
};
bs.a = 7; bs.b = 7;
cout<<bs.a<<bs.b<<endl;
结果为7 -1,单个位域也分有符号无符号数
4. C++标准库 bitset类