“位运算”助力高性能开发

0x00 -- 位运算概览

符号描述运算规则
&按位与2个位都为1,结果为1
按位或一个位为1,结果为1
^按位异或相同为0,相异为1
~按位取反1变0,0变1
<<n左移各二进位全部左移n位,高位丢弃,低位补0
>>n右移各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)

0x01 -- 按位与 &

运算规则:0&0=0 0&1=0 1&1=1

两位相同为1,否则为0

3 & 5 = 1
3 0000 0011
5 0000 0101
& 0000 0001

用途

  • 清零

如果想将一个单元清0,即让这个数的各个位都为0,就让这个数去与一个各位都为0的数值按位与。结果为0

  • 取一个数的指定位

举个例子:

a = 1010 1110. 取 a 的低四位。只需要找一个 b,把 b 的低四位设置为 1,其余为 0,即

b = 0000 1111.

& = 0000 1110. 就可以得到 a 的指定部分, 这个过程中 也就是 的(mask)所谓的掩码。

  • 判断奇偶

只要根据末尾是 还是 来判断是否是奇偶数。

是 0 就是偶数,是 1 就是奇数。因此可以代替 if (a % 2) == 0

替换为 if(a & 1 == 0)来判断 是否为偶数。

0x02 -- 按位与 |

运算规则:0|0 = 0, 0|1 = 1, 1|1 = 1

只要其中一位是 1, 结果就位 1.

3 | 5 = 7
3 0000 0011
5 0000 0101
| 0000 0111

用途

  • 用来对一个数据的某些位设置位 1

举个例子:

a = 1010 1110. 设置 a 的低四位为 1。只需要找一个 b,把 b 的低四位设置为 1,其余为 0,即

b = 0000 1111.

| = 1010 1111. 就可以得到按位与后的结果,

0x03 -- 按位异或 ^

运算规则:0 ^ 0 = 0, 0 ^1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0

参加元算的俩个数,相同的位为 0,不同的位为 1 ;

异或的几条性质:

  1. 交换律

  2. 结合律 ( a ^ b ) ^ c == a ^ ( b ^ c )

  3. 对于任何数 x,都有 x ^ x = 0,x ^ 0 = x

  4. 自反性: a ^ b ^ b = a ^ 0 = a;

用途

  • 翻转指定位

    举个例子:

    a = 1010 1110, 翻转 a 的低四位。只需要找一个 b,把 b 的低四位设置为 1,其余为 0,即

    b = 0000 1111.

    ^ = 1010 0001. 就可以得到按位异或后的结果。 就把 a 的低四位按位翻转了。

  • 与0相异或值不变

      1010 1110
      0000 0000
    ^ 1010 1110
      a   3 0000 0011
      b   4 0000 0100
      a ^ b 0000 0111 a
         
      b   4 0000 0100
      b ^ a 0000 0111 a
      	    0000 0011 b
  • 交换俩个数

    void swap(int a, int b) {
      if(a != b) {
        a ^= b;
        b ^= a;
        a ^= b;
      }
    }

0x05 -- 按位取反 ~

运算规则: ~1 = 0, ~0 = 1

使 a 的最低位为 0,可以表示为:a & ~1。~1 的值为 1111 1111 1111 1110,再按"与"运算,最低位一定为0。因为“ ~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。

0x06 -- 左移运算符 <<

使 a 的最低位为 0,可以表示为:a & ~1。~1 的值为 1111 1111 1111 1110,再按"与"运算,最低位一定为 0。因为 “ ~” 运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。

0x07 -- 右移运算符 >>

定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

例如:a = a >> 2 将 a 的二进制位右移 2 位,左补 0 或者 左补 1 得看被移数是正还是负。

操作数每右移一位,相当于该数除以 2。

综合应用

比如有两个 int 类型变量 x、y,首先要求 x+y 的和,再除以 2,但是有可能 x+y 的结果会超过 int 的最大表示范围,所以位运算就派上用场啦。

(x & y)+((x ^ y) >> 1);


对于一个大于0的整数,判断它是不是2的几次方

`((x & (x - 1)) == 0) && (x != 0);


求绝对值

int abs( int x ) { 
   int y ; 
   y = x >> 31 ; 
   return ( x ^ y) - y ;        //or: (x + y) ^ y 
}

取模运算,采用位运算实现:

a % (2 ^ n) 等价于 a & (2 ^ n - 1)


乘法运算 采用位运算实现

a * (2 ^ n) 等价于 a << n


除法运算转化成位运算

a / (2 ^ n) 等价于 a >> n


求相反数

(~x + 1)


a % 2 等价于 a & 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值