美文网首页
[Java] 移位运算2,你可能不知道的运算

[Java] 移位运算2,你可能不知道的运算

作者: 灰灰手记 | 来源:发表于2017-05-09 00:49 被阅读120次

    [Java] 移位运算1
    前一篇笔记已经介绍了 Java 移位运算的基本概念和注意事项,接下来将介绍你可能不知道的移位运算。


    现象

    先看下面的代码:

    System.out.println(1 << 31);
    System.out.println(1 << 32);
    System.out.println(1 << 33);
    System.out.println(1 << 34);
    System.out.println(1 << 35);
    

    这里的 1 默认是 int 型,32 位。那讲道理左移 31 位就已经满了,再移动就超出了 32 位限制,就应该变为 0 了。但实际结果是这样的:

    没有看错,确实没有如我们所想变成 0,反而看起来是对 32 取模之后再以的。
    因为不知道上哪去查 Java 移位运算的具体定义,所以多用了几组数据进行测试:

    假如我们要对 num 左移 dis 位:
    num << dis

    1. 当右操作数 dis >= 0 时,很明显就是先对 dis 取模运算:
      newDis = dis % (num类型长度)
      然后再 num << newDis
    2. 当右操作数 dis < 0 时,就不是先对 dis 取模了,
      因为在 Java 里面 -30 % 32 = -30,运算方法请看 [Java] 取模运算
      这里反而看起来是 newDis = dis + (num类型长度)*n,n 取使 newDis >= 0 的最小值,
      最后再 num << newDis
    总结

    都换成递归加减法的思想整理一下:
    dis >= 0 时,newDis = dis - (num类型长度)*n,n 取使 newDis >= 0 的最大值;
    dis < 0 时,newDis = dis + (num类型长度)*n,n 取使 newDis >= 0 的最小值。
    但这只是我们通过现象总结出来的结论,没有理论依据,仅供参考。


    Java 移位运算定义

    最后本人在知乎上提问:Java移位运算超过了会怎样?
    感谢知乎大神Kyo Iori的解释,
    感谢知乎大神木女孩找来的Java移位运算定义:

    Chapter 15. Expressions
    If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1**) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.
    If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1**) with the mask value 0x3f (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.

    这段话简单概括就是:
    如果左操作数是 int 型,则取右操作数的低 5 位的值作为移动位数,因为低 5 位的值正好在 0~31 之间;
    如果左操作数是 long 型,则取右操作数的低 6 位的值作为移动位数,因为低 6 位的值正好在 0~63 之间。

    这时我们再来看前面的例子:


    因为这里的 1 默认为 int 型,所以我们先将 33、97、-30、0、35依次转为二进制并取低 5 位值:

     33 = 00000000 00000000 00000000 001 00001 = 00001 = 1
     97 = 00000000 00000000 00000000 011 00001 = 00001 = 1
    -30 = 11111111 11111111 11111111 111 00010 = 00010 = 2
      0 = 00000000 00000000 00000000 000 00000 = 00000 = 0
     35 = 00000000 00000000 00000000 001 00011 = 00011 = 3
    

    显然,33、97 的低 5 位都是 00001 = 1,所以
    1 << 33 = 1 << 97 = 1 << 1 = 2
    而 -30 的低 5 位是 00010 = 2,所以
    1 << -30 = 1 << 2 = 4
    已经很好理解了,其他就不过多解释了。


    [Java] 移位运算1

    相关文章

      网友评论

          本文标题:[Java] 移位运算2,你可能不知道的运算

          本文链接:https://www.haomeiwen.com/subject/ixnvtxtx.html