位运算

二进制基础

二进制的位

在机器内部,信息的表示和存储依赖于机器硬件电路的状态。又因为电路只有 “开” 和 “关” 两种状态,因此计算机只能识别“0”和“1”。所以信息的表示(数据)在计算机中是一串01的组合。

二进制与十进制之间的互转

二进制转十进制

进制数的每一位都有一个位权,从右往左是低位到高位,X进制数从右往左数的第i位(从0开始)的位权是X ^ i。

通过计算每一位上的数字与位权的积之和,就可以把X进制数转化成10进制数。

如十进制数567 = 5 * 100(10 ^ 2) + 6 * 10(10 ^ 1) + 7 * 1(10 ^ 0) = 567。(5的位权是10 ^ 2,6的位权是10 ^ 1)

八进制数1067 = 1 * 512(8 ^ 3) + 0 * 64(8 ^ 2) + 6 * 8(8 ^ 1) + 7 * 1(8 ^ 0) = 567

二进制数10110 = 1 * 16(2 ^ 4) + 0 * 8(2 ^ 3) + 1 * 4(2 ^ 2) + 1 * 2(2 ^ 1) + 0 * 1(2 ^ 0) = 22

十进制转二进制

使用短除法。

如下,比如十进制数156要转二进制。

最终得到10011100。(如上)

计算一下,1 * 128 + 0 * 64 + 0 * 32 + 1 * 16 + 1 * 8 + 1 * 4 + 0 * 2 + 0 * 1 = 156。

原码、补码、反码

正数的原码、补码、反码都相同。

负数的反码就是原码所有位(除符号位)取反,补码就是反码 + 1。

十六位正整数原码、反码、补码

注:最高位是符号位,0代表正数,1代表负数。

基本位运算

每一位的位运算

按位与(&)

0 & 0 = 0

0 & 1 = 0

1 & 1 = 1

按位或(|)

0 | 0 = 0

0 | 1 = 1

1 | 1 = 1

按位非[取反](~)

~0 = 1

~1 = 0

按位异或(^)

0 ^ 0 = 0

0 ^ 1 = 1

1 ^ 1 = 0

按位与、按位或图片

常见位运算

  1. 判X奇偶:X & 1
  2. X * (2 ^ N):X << N
  3. X / (2 ^ N)(向下取整): X >> N
  4. X * 10:(X << 3) + (X << 1)
  5. 取X二进制下的第N位:1 << N & X
  6. 设置X的第N位为1:X |= 1 << N
  7. 设置X的第N位为0:X &= 1 << N ^ X
  8. 求X从低位到高位第一个1的位权:X & -X

C++运算符优先级

位运算的应用

  1. 多重背包通过二进制拆分转化成01背包。比如有X个物品,就把X进行二进制拆分即可。https://blog.csdn.net/weixin_43914593/article/details/123703237
  2. 非递归形式求X ^ Y % Mod 的结果。
  3. 求所有子集的位操作方法。https://blog.csdn.net/yanzhenhuai/article/details/81572028