位运算及常见用例
导言
众所周知,计算机是以二进制来储存数据的,而我们所使用的十进制甚至十六进制,都是通过特定的程序进行转化而得来的,如果我们跳过这些转换,直接对底层的位进行运算,是不是效率会更高呢?
常见位运算符
符号 | 解释 | 用例 |
---|---|---|
& | 按位与:都是_1_才取1 | 0011 & 1011 = 0011 |
| | 按位或:有_1_取_1_,无_1_取_0_ | 0011 & 1011 = 1011 |
~ | 按位取反:0 = = >1;1 = = >0 | ~0011 = 1100 |
^ | 按位异或:相同取_0_,不同取_1_ | 0011 ^ 1011 = 1000 |
<< | 左移:将所有位向左边移动指定单位,相当于乘以2 | 0011 << 1 = 0110 |
>> | 右移:将所有位向右边移动指定单位,相当于除以2 | 0011 << 1 = 0001 |
- 注意区别 ~ 和 ! : ~ 是按照二进制位取反,每一位都会操作,包括符号位 ;**!**是逻辑或,只能够将 0 和 非0 之间互相转换。
- ^ 异或运算符的性质:
- 交换律:a^b == b^a
- 结合律:abc == a(bc)
- 自反性:abb == a^0 == a
- 不同类型字符位运算时,数位右对齐,空位根据不同情况补齐:
- 正数补0;
- 负数补1;
- 无符号补0;
常见用法
- a & 0000 0110:取a的二进制的后二三位(无正负之分)
- a & 0000 0110:a的后二三位设为1,其余位不变。
- a &~ 0000 0110:使后二三位变为0
- a ^ 0000 0110:将a的后二三位翻转(0==》1;1==》0)
- (a >> 5) | ( a << 3):高5位和低3位交换(0001 1010==》1101 0000),a只能有8位
- a & ( a - 1 ):最右边的_1_变成_0_
- _a[0]a[1]…a[n]b[0]b[1]…b[n-1]_查找a中有而b中确实的数,这里只能有一个数;
- 二进制字符反转见LeetCode君的解释
a=b=a^=b:交换a和b,好处是不需要额外的变量,但是效率比较低,且可读性很差,不建议使用。- ~
a+1:符号取反,效率和a=-a
差不多(虽然在我的电脑上测试后者更快),但是可读性差,不建议使用。 二进制求最大公约数,效率低下,不建议使用,不过可以学习一下算法。