| 运算符 | 解释 |
| :-------------: | :---------------------: |
-| `&` | 只有在两个(对应位数中)都为 1 时才为 1 |
-| <code>\|</code> | 只要在两个(对应位数中)有一个 1 时就为 1 |
-| `^` | 只有两个(对应位数)不同时才为 1 |
+| `&` | 只有在两个(对应位数中)都为 1 时才为 1 |
+| `\|` | 只要在两个(对应位数中)有一个 1 时就为 1 |
+| `^` | 只有两个(对应位数)不同时才为 1 |
`^` 运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变,即 `(a ^ b) ^ b = a` 。
> 举例:
->
-> $$
-> \begin{aligned}
-> &5&=&&(101)_2\\
-> &6&=&&(110)_2\\
-> &5\tt\,\&\,6\rm&=&&(100)_2&=\ 4\\
-> &5\tt\,|\,\rm6&=&&(111)_2&=\ 7\\
-> &5\tt\,\text{^}\,\rm6&=&&(011)_2&=\ 3\\
-> \end{aligned}
> $$
+\begin{aligned}
+&5 &=(101)_2\\
+&6 &=(110)_2\\
+&5\tt\,\text{&}\,\rm6 &=(100)_2 &=\ 4\\
+&5\tt\,\text{|}\,\rm6 &=(111)_2 &=\ 7\\
+&5\tt\,\text{^}\,\rm6 &=(011)_2 &=\ 3\\
+\end{aligned}
+$$
## 取反
补码——正数的补码为其(二进制)本身,负数的补码是其(二进制)取反后 $+1$ 。
> 举例:
->
-> $$
-> \begin{aligned}
-> 5=(0000\ 0101)_2\\
-> 5\ \text{的补码} =(1111\ 1010)_2\\
-> \tt\ \text{~}\rm5=(1111\ 1010)_2
-> \end{aligned}
> $$
+\begin{aligned}
+5=(0000\ 0101)_2\\
+5\ \text{的补码} =(1111\ 1010)_2\\
+\text{~}5=(1111\ 1010)_2
+\end{aligned}
+$$
## 左移和右移
右移( `>>` )将转化为二进制后的数字整体向右移动。
> `num >> i` //表示将 $num$ 转换为二进制后向右移动 $i$ 位(所得的值)
->
-> 举例:
->
-> $$
-> \begin{aligned}
-> &5&&=&&(00000101)_2\\
-> &5\tt\,<<\,\rm1&&=&&(00001010)_2\!\!\!&=&&\!\!\!10\\
-> &5\tt>>\rm1&&=&&(00000010)_2&=&&2
-> \end{aligned}
+
+举例:
+
> $$
+\begin{aligned}
+&5&=&\ (00000101)_2\\
+&5\,<<\,1&=&\ (00001010)_2\,&=&\ 10\\
+&5\,>>\,1&=&\ (00000010)_2\,&=&\ 2
+\end{aligned}
+$$
在 C++ 中,右移操作中右侧多余的位将会被舍弃。而左侧较为复杂:对于无符号数,会在左侧补 0;而对于有符号数,则会用最高位的数补齐(Replicate most significant bit on left)。
而对应的位运算也就可以看作是对集合进行的操作。
| 操作 | 集合表示 | 位运算语句 |
-| --- | ----------------: | :----------: |
+| --- | :----------------: | :----------: |
| 交集 | $a \cap b$ | `a & b` |
-| 并集 | $a \cup b$ | `a | b` |
+| 并集 | $a \cup b$ | `a \| b` |
| 补集 | $\bar{a}$ | `~a` |
| 差集 | $a \setminus b$ | `a & (~b)` |
| 对称差 | $a\triangle b$ | `a ^ b` |