Bitwise Operation - tenji/ks GitHub Wiki

位运算

一、概念

什么是位运算?

程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。

位运算就是直接操作二进制数,那么有哪些种类的位运算呢?

二、常见位运算符

常见的运算符有与(&)、或(|)、异或(^)、取反(~)、左移(<<)、右移(>>是带符号右移 >>>无符号右移动)。下面来细看看每一种位运算的规则。

2.1 与 &

规则:二进制对应位两两进行逻辑 AND 运算(只有对应位的值都是 1 时结果才为 1, 否则即为 0)即:0 & 0 = 0, 0 & 1 = 0, 1 & 1 = 1

例如:2 & -2

2.2 或 |

规则:二进制对应位两两进行逻辑或运算(对应位中有一个为 1 则为 1) 即:0 | 0 = 0, 0 | 1 = 1, 1 | 1 = 1

例如:2 | -2

2.3 异或 ^

规则:二进制对应位两两进行逻辑 XOR (异或) 的运算(当对应位的值不同时为 1, 否则为 0)即:0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 1 = 0

例如:2 ^ -2

2.3.1 十六进制的异或运算(字符串转十六进制、十进制、二进制)
private static String oxr(String hexStrLeft, String hexStrRight) {
    // 先通过 Integer.valueOf(String s, int radix) 方法转为十进制数字
    int decLeft = Integer.valueOf(hexStrLeft, 16);
    int decRight = Integer.valueOf(hexStrRight, 16);

    int res = decLeft ^ decRight;

    // 使用 Integer.toHexString(int i) 方法将异或计算的结果转成十六进制字符串
    return Integer.toHexString(res).toUpperCase();
}

2.4 按位取反 ~

规则:二进制的 0 变成 1,1 变成 0。

2.5 移位运算符

左移运算 <<:左移后右边位补 0

右移运算 >>:右移后左边位补原最左位值(可能是 0,可能是 1)

右移运算 >>>:右移后左边位补 0

  • 对于左移运算符 << 没有悬念右侧填个零无论正负数相当于整个数乘以2。
  • 而右移运算符就有分歧了,分别是左侧补 0 >>>和左侧补原始位 >>,如果是正数没争议左侧都是补 0,达到除以 2 的效果;如果是负数的话左侧补 0 >>> 那么数值的正负会发生改变,会从一个负数变成一个相对较大的正数。而如果是左侧补原始位(负数补 1) >> 那么整个数还是负数,也就是相当于除以 2 的效果。

三、位运算小技巧

3.1 判断奇偶数

正常判断奇数偶数的时候我们会这样写:

if ( n % 2 == 1) {
    // n 是个奇数
}

使用位运算可以这么写:

if (n & 1 == 1) {
    // n 是个奇数。
}

其核心就是判断二进制的最后一位是否为 1,如果为 1 那么结果加上 2^0 = 1 一定是个奇数,否则就是个偶数。

3.2 交换两个数

对于传统的交换两个数,我们需要使用一个变量来辅助完成操作,可能会是这样:

int team = a;
a = b;
b = team;

但是使用位运算可以不需要借助额外空间完成数值交换:

a=a^b; // a = a^b
b=a^b; // b = (a^b)^b = a^0 = a
a=a^b; // a = (a^b)^(a^b^b) = 0^b = 0

3.3 二进制枚举

四、位运算经典问题

参考链接

⚠️ **GitHub.com Fallback** ⚠️