位运算技巧归纳

1. 位运算基本操作

逻辑运算

a = 1 0 0 1 1
b = 1 1 0 0 1
与运算 &  a & b = 1 0 0 0 1    //都为1时为1,否则为0
或运算 |  a | b = 1 1 0 1 1    //都为0时为0,否则为1
非运算 ~    ~ a = 0 1 1 0 0    //所有位1变成0,0变成1
异或 ^    a ^ b = 0 1 0 1 0    //相同为0,不同为1

移位操作:左移和右移
对于左移,直接丢弃高位,低位补0即可;但是对于右移,丢弃低位,高位应该补什么?此时出现两种右移方式,算术右移和逻辑右移
算术右移:左端补上最高位
逻辑右移:左端直接补0
几乎所有的编译器/机器组合都对有符号数使用算术右移,而程序员编写程序时也都假设机器是这样实现的;对于无符号数,右移必须是逻辑的。

2. 巧妙使用位运算

1. 乘除

int a = 4;
a >> 1;  //a=2
a << 2;  //a=8

2. 交换

void swap (&a,&b){
	a ^= b;
	b^ = a;
	a ^= b;

3. 奇偶校验

if(0==a&1)  //为真则是奇数,为假则是偶数

4. 正负数转换

int reverse(int a){
	return ~a+1;
}

5. 求绝对值

int abs(int a){
	int i = a>>31;                  //根据符号位判断正数还是负数
	return i==0 ? a : (~a+1);       //正数直接输出。负数取反加1
}

优化方法:
int abs(int a){
	int i = a >>31;              //正数则i=0,负数则i为Oxffffffff
	return ((a ^ i)- i);        //与Ox异或相当于取反,再-i其实就是加1

6. 高低位互换

unsigned short a = 34543;   //只适用于无符号数
a = (a >> 8 | a << 8);

7. 统计二进制表示中1的个数

int a = 13
int count = 0;
while(a){  
  a = a & (a - 1);  
  count++;  
}
第一次循环
  a = 1 1 0 1
a-1 = 1 1 0 0  
容易看出低位的1直接没了,a = 1 1 0 0
第二次循环
  a = 1 1 0 0
a-1 = 1 0 1 1
再次消掉低位的1,循环往复即可

3. bitset 使用

头文件 #include

1. 初始化

bitset<16>bits;                                 //0000000000000000
bitset<16>bits(Oxff);                          //1111111111111111
bitset<16>bits(std::string("001100110011"));  //0000001100110011

2. 常用函数

bits.size()                        //位数
bits.none()                       //返回是否没有1
bits.any()                        //返回是否有1
bits.count()                      //返回1的个数
bits.set()                       //全部置1
bits.reset()                    //全部置0
bits.set(p)/bits.reset(p)        //第p+1位置1/0
bits.flip()                   //全部取反
bits.flip(p)                    //第p+1位取反
bits.to_string()                  //返回转换后的字符串

你可能感兴趣的:(C++,补码)