java中的移位操作详解

移位运算,这是一个陌生又熟悉的操作。陌生是指不易理解且不常用,熟悉是指“别人家的开发工程师”在代码中经常使用这种方式进行高低位的截取、哈希计算、乘除法的运算,今天,让我们一起来揭开移位运算的神秘面纱。

Java提供了两种带符号位的移位操作,左移 << 和右移 >>,此外,Java还提供了一种无符号右移操作 >>>。下面我们一起来研究如何正确的使用它们。

带符号位的移位操作规则如下:只有负数右移的时候,高位补1,其他情况的补位,都只补0。

下面以8位二进制的移位进行举例。

  10的补码为00001010,左移一位变成20(00010100),右移一位变成5(00000101)
  5的补码为00000101,左移一位变成10(00001010),右移一位变成2(00000010)
  -99的补码为10011101,左移一位变成58(00111010),右移一位变成-50(11001110)

总结几点注意事项:

  • 左移一位近似于乘以2,右移一位近似于除以2。当十进制的奇数时,由于二进制表示的时候最低位为1,右移的时候最低位被舍弃,故不是精准的除以2。
  • 左移有可能改变数的正负。如果左移一位的时候,符号位和数值最高位不同,则数的正负发生变化。
  • 如果是32位处理器,则移动的位数是一个mod 32的结果,即>>1和>>33是一样的结果,可以理解为在进行移位之前,对要移动的位数先取模运算。

程序验证:
System.out.println(Integer.MAX_VALUE << 1);
输出-2。32位int的最大数为01111111111111111111111111111111,左移一位为11111111111111111111111111111110,表示的十进制数为-2。

System.out.println(Integer.MIN_VALUE << 1);
输出0。32位int的最小数为10000000000000000000000000000000,左移一位为00000000000000000000000000000000,表示的十进制数为0。

无符号位的右移操作规则如下:不管正负数,高位都补0。

总结几点注意事项:

  • 正数移动最大位数的最小值为0,负数移动最大位数的最小值为1。因为正数的符号位为0,负数的符号位为1,当移最大位数后,二进制除了最低位为符号位,其他全是0。
    java中的移位操作详解