抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

介绍

  在位移方向上,有左移和右移。在移位策略上,有逻辑移位和算术移位。两个维度互相组合有4中组合。

逻辑左移=算数左移,右边统一添0
逻辑右移,左边补上符号位
算术右移,左边补 0

e.g:1010101010,其中[]是添加的位

逻辑左移一位:010101010[0]
算数左移一位:010101010[0]
逻辑右移一位:[0]101010101
算数右移一位:[1]101010101

左移

  首先,左移运算会溢出符号位,负数在左移之后可能会变成正数。在小于变量容器一半的变量可以通过左移一位来做乘2的运算。在不考虑溢出的情况下,其左移后的数与左移前的数关系如下:

1
2
3
4
5
a << 1   =>   a = a * 2^1;
a << 2 => a = a * 2^2;
a << 3 => a = a * 2^3;
...
a << x => a = a * 2^x;

逻辑右移和算术右移

  逻辑右移也有和左移一样的规律,但是除法会丢失小数点精度

1
2
// 逻辑右移
a >> x => a = a ÷ 2^x;
1
2
3
4
1010 1010 做逻辑右移
1010 1010,-86
1101 0101,-43
1110 1010,-22

  用 java 做算术右移,要小心 byte 在算术右移中会自动转型为 int ,高位补1,导致的byte计算时逻辑右移和算术右移结果一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* 1010 1010,-86
* 1101 0101,-43
* 1110 1010,-22
* 这一定是因为 byte 在做运算时被转型为了 int,在转型为 int时采用了高位补1的补码算法,导致算术移位之后结果和逻辑移位一样
*/
public static void test2() {
byte a = (byte) 0xaa;
System.out.println(byteBinary(a) + "," + a);
a = (byte) (a >>> 1);
System.out.println(byteBinary(a) + "," + a);
a = (byte) (a >>> 1);
System.out.println(byteBinary(a) + "," + a);
}

评论