我们在看别的犇犇写代码的时候会发现有很多的符号我们不认识,给大家解释一下常见的位运算符

按位操作是以二进制来进行从右到左进行按位操作的

按位与

按位与 & 是按位进行按位对比的时候如果都是 1 那么就是 1,其余情况都是 0,因为 1 就是 True 0 就是 False

算了,不给那么灌输这么多了,在按位或里你自然而然就懂了

#include <bits/stdc++.h>

using namespace std;

int main() {
	cout << (13 & 17); // 别忘了加括号
	return 0;
}

你猜猜运行结果是什么?是 1 !

解析如下:

01101   // 13
10001   // 17
-------  // 向右对齐, 不够补0,老规矩
00001 = 1

按位或

按位或 | 是在二进制里相同或只有一个是1时为1,都是 0 的时候就是 0

其实这个就是和 &&、|| 差不多,不过这个按位是以一个二进制位来进行逻辑的

#include <bits/stdc++.h>

using namespace std;

int main() {
	cout << (13 | 17); 
	return 0;
}

答案给你们计算吧

01101
10001
-----
11101

11101 对应的是 1+4+8+16=29 (8421法,不会看下面)

所以 13 | 17 = 29

小补充(8421)

这种方式可以用到二进制转十进制、十六进制、八进制中

首先说转十进制,我们要把二进制下的 1011001 转成十进制:

1  0  1  1  0  0  1
64 32 16 8  4  2  1  // 把位数对应的二次幂写出来,其实就是 2的n次方,n 从0开始
-------------------
1+8+16+64=86

所以 1011001 的十进制是 86

按位异或(异或运算)

按位异或 ^ ,看这样子像个乘方运算,但是 Python老油条会这么想:“不是 ** 吗?怎么又有了 ^ 了?!”

实际上按位异或就是在二进制位一样的时候为 0 其余情况为1

13 ^ 17 的结果是这样的:

01101
10001
-----
11100 = 28

所以结果就是 28

按位取反(获得补码)

按位取反 ~ 可不是什么两个二进制数进行按位操作的,是源码变补码,也就是我们长说的反码加一。正数变负数都知道吧

~13 的结果为 -14

左移

左移 << 是较常见的一种运算符,他是以二进制进行左移的

10 << 1 = 20

1010
左移 1 位是以二进制数本身进行左移,左边不限制,右边始终保持
10100 = 20

左移 1 位就是乘二,因为在8421法中,一半的一半进行乘2就是本身乘二(分配律不信你们没学过!)

nn 左移 kk 位就是 n2k1n·2^{k-1}

右移

右移 >> 也是常见的,比如在快速幂、二分里出现((l + r) >> 1)其实我们大概可以猜测到,右移其实就是左边空0,右边的线始终保持不动,也就是右移的位数在二进制里就删除了

10 >> 1 = 5

1010
----
 101

右移一位是除以2,右移 kk位是 n2k1\frac{n}{2^{k-1}}

后记

所以按位异或和按位与、按位或有什么用处呢