一. 位操作符
1. & 与运算
两个位都是 1 时,结果才为 1,否则为 0。
特性:
-
2. | 或运算
3. ^ 异或运算
两个位相同则为 0,不同则为 1。
概念:找不同。可用来去除冗余
特性: 0异或任何数=任何数
- 1异或任何数 = 任何数取反
-
4. ~ 取反运算
5. << 左移运算
6. >> 右移运算
向右进行移位操作,对无符号数,高位补 0,对于有符号数,高位补符号位。
二. 运用
1. 实现乘除
2. 指定位取反
3. 两值交换
4. 判断奇偶
5. 交换符号
6. 求绝对值
int i = a >> 31; //正数i=0; 负数i=-1;
i == 0 ? a : (~a + 1);
优化:((a^i)-i) //正数((a^0)-0); 负数((a^0xffffffff)-(-1)) 等同于取反+17. 高低位交换(无符号)
8. 二进制逆序
将无符号数的二进制表示进行逆序,求取逆序后的结果,如
数34520的二进制表示:10000110 11011000逆序后则为:00011011 01100001它的十进制为7009
在字符串逆序过程中,可以从字符串的首尾开始,依次交换两端的数据。在二进制中使用位的高低位交换会更方便进行处理,这里我们分组进行多步处理。
第一步:以每 2 位为一组,组内进行高低位交换
交换前: 10 00 01 10 11 01 10 00交换后: 01 00 10 01 11 10 01 00
第二步:在上面的基础上,以每 4 位为 1 组,组内高低位进行交换
交换前: 0100 1001 1110 0100交换后: 0001 0110 1011 0001
第三步:以每 8 位为一组,组内高低位进行交换
交换前: 00010110 10110001交换后: 01100001 00011011
第四步:以每16位为一组,组内高低位进行交换
交换前: 0110000100011011交换后: 0001101101100001
对于上面的第一步,依次以 2 位作为一组,再进行组内高低位交换,这样处理起来比较繁琐,下面介绍另外一种方法进行处理。先分别取原数 10000110 11011000 的奇数位和偶数位,将空余位用 0 填充:
原数: 10000110 11011000 奇数位: 10000010 10001000 偶数位: 00000100 01010000再将奇数位右移一位,偶数位左移一位,此时将两个数据相或即可以达到奇偶位上数据交换的效果:
原数: 10000110 11011000 奇数位右移一位: 0 10000010 1000100 偶数位左移一位:0000100 01010000 0 两数相或得到: 01001001 11100100上面的方法用位操作可以表示为:
取a的奇数位并用 0 进行填充可以表示为:a & 0xAAAA
- 取a的偶数为并用 0 进行填充可以表示为:a & 0x5555 因此,上面的第一步可以表示为:
a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1)
同理,可以得到其第二、三和四步为:
a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2)
a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4)
a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8)
因此整个操作为:unsigned short a = 34520; a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1); a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2); a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4); a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8);9. 位操作统计二进制中 1 的个数
count = 0 while(a){ a = a & (a - 1); //消去 count++; }10.
