[JAVA]移位运算(左移<<,右移>>和无符号右移>>>)

时间:2021-09-07 13:08:09

一、背景知识  

  整数在内存中是以二进制的形式存在的,而且存的是该整数的补码。最高位代表符号位,正数为0,负数为1

  正数的补码是其二进制本身,负数的补码则是 符号位保持1不变,其他位按位取反再加1,+0和-0的补码相同,都是0。

  负数在进行按位与运算时是以补码形式参与运算。(这个很好理解,因为负数在内存中本身就是以补码存储的)

二、移位运算

  下面介绍三种移位运算,

  首先我们对5作运算。

  5在内存中的存储形式为:0000 0000 0000 0000 0000 0000 0000 0101

  1、左移<<

   符号位会被保留,数值位左移一位,低位补0,变为:

   0000 0000 0000 0000 0000 0000 0000 1010

   得到值为10

  2、右移>>

   符号位会被保留,数值位左移一位,数值位高位补0,变为:

   0000 0000 0000 0000 0000 0000 0000 0010

   得到值为2

  可以看到,左移相当于乘以2,右移相当于除以2,JDK中很多源码都采用了这种写法,效率高而且优雅

  3、无符号右移>>>

   >>>在右移时会将符号位当做数值位处理,一起右移,高位补0

   为了清楚地演示出符号位的变化,以-5为例:

   -5在内存中的存储形式为:1111 1111 1111 1111 1111 1111 1111 1011

   >>>1      后得到:   0111 1111 1111 1111 1111 1111 1111 1101

   值为2147483645,很明显,无论从10进制数值,还是从内存中的存储,都能看出,该值比Integer的最大值小2

   代码如下:

/**
* @Description:
* @projectName:JavaTest
* @see:PACKAGE_NAME
* @author:郑晓龙
* @createTime:2019/5/15 23:30
* @version:1.0
*/
public class ShiftOperationTest {
public static void main(String[] args) {
System.out.println(5<<1);
System.out.println(5>>1);
System.out.println(-5>>>1);
System.out.println(Integer.MAX_VALUE);
}
}

  运行结果:

10
2
2147483645
2147483647

最后,强迫症来了,为什么没有<<<

我认为是这样的:内存中是将整数以二进制的补码形式存放,最高位是符号位,左移时最高位有可能是1或0,符号位不能确定,也就无法满足无符号左移的定义,而右移可以规定高位补0,即可以确保符号位为0。