Java位运算1_左移、右移

左移运算(«)

value << num

num 指定要移位值;value 移动的位数。

将左操作数(value)转为二进制数后向左边移动 num 位,并且在低位补 0,高位丢弃。

例如:5 « 2

0000 0000 0000 0000 0000 0000 0000 0101     5 的补码(同原码)
0000 0000 0000 0000 0000 0000 0001 0100     左移 2 位后,低位补 0。换算成 10 进制为 20

如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模。如:对 int 类型(最大位数 32)的数值移动 33 位,实际上只移动了 33 % 32 = 1 位。

注:n 位二进制,最高位为符号位,因此表示的数值范围:−2(𝑛−1) —— 2(𝑛−1)−1,所以模为:2(𝑛−1)。

在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以 2 的 1 次方,左移 n 位就相当于乘以 2 的 n 次方。如:5 « 2 相当于 5∗22=20。

如果移进高阶位(int 31 或 long 63 位),那么该值将变为负值。如:1 « 31 = -2147483648

右移运算(»)

value >> num

num 指定要移位值;value 移动的位数。

将左操作数(value)转为二进制数后向右边移动 num 位,符号位不变,高位补上符号位(若左操作数是正数,则高位补 0,若左操作数是负数,则高位补 1),低位丢弃。

右移时,被移走的最高位(最左边的位)由原来最高位的数字补充,这叫做符号位扩展(保留符号位)(sign extension),在进行右移操作时用来保持负数的符号。

例如:7 » 2

0000 0000 0000 0000 0000 0000 0000 0111     7 的补码(同原码)
0000 0000 0000 0000 0000 0000 0000 0001     右移 2 位后,高位补 0。换算成 10 进制为 1

例如:-7 » 2

1000 0000 0000 0000 0000 0000 0000 0111     -7 的原码
1111 1111 1111 1111 1111 1111 1111 1000     -7 的反码
1111 1111 1111 1111 1111 1111 1111 1001     -7 的补码
1111 1111 1111 1111 1111 1111 1111 1110     右移 2 位后,高位补 1
1000 0000 0000 0000 0000 0000 0000 0010     补码转原码。换算成 10 进制为 -2

正数右移 n 位相当于除以 2 的 n 次方并且舍弃了余数。如:7 » 2 相当于: 7/22=1。

负数右移 n 位相当于除以 2 的 n 次方,如果有余数 -1。如:-7 » 2 相当于: 7∗22−1=−2。

例子:

public static void main(String[] args) {

        // 左移
        int i = 16;

        // 在二进制i的右边加两个零,也就是二进制乘以100
        // 100换算成10进制,乘以4
        // 也可能看作是乘以2的2次幂
        int i1 = i << 2;

        int i2 = i * (2 * 2);

        System.out.println("i1 = " + i1 + ", i2 = " + i2);

        // 在二进制i的右边加三个零,也就是二进制乘以1000
        // 1000换算成10进制,乘以8
        // 也可能看作是乘以2的3次幂
        int i3 = i << 3;

        int i4 = i * (2 * 2 * 2);
        System.out.println("i3 = " + i3 + ", i4 = " + i4);
// --------------------------------------------------------

        // 右移
        int j = 16;

        // 在二进制i的右边减少两个零,也就是二进制除以100
        // 100换算成10进制,除以4
        // 也可能看作是除以2的2次幂
        int j1 = j >> 2;
        int j2 = i / (2 * 2);

        System.out.println("j1 = " + j1 + ", j2 = " + j2);

    }

无符号右移(»>)

value >>> num

num 指定要移位值;value 移动的位数。

将左操作数(value)转为二进制数后向右边移动 num 位,0 补最高位(忽略了符号位扩展)。

无符号右移运算只是对 32 位和 64 位的值有意义。

例如:-7 »> 2

1000 0000 0000 0000 0000 0000 0000 0111     -7 的原码
1111 1111 1111 1111 1111 1111 1111 1001     -7 的补码
0011 1111 1111 1111 1111 1111 1111 1110     右移 2 位后,高位补 0。换算成 10 进制为 1073741822