【问题标题】:bit shift operation does not return expected result位移位操作不返回预期结果
【发布时间】:2012-03-26 22:45:32
【问题描述】:

为什么当我位移1 时Java返回-2147483648

预期结果是9 223 372 036 854 775 808,用 Wolfram Alpha 和我的计算器测试。

我测试过:

System.out.print((long)(1 << (63)));

【问题讨论】:

    标签: java bit-manipulation bit-shift


    【解决方案1】:

    关于这条线有一件重要的事情需要注意

    System.out.print((long)(1 << (63)));
    

    你先取(1 &lt;&lt; 63),然后然后你投长。结果,您实际上是在整数中左移,因此长转换没有任何效果。这就是为什么左移 63 位给出最小整数而不是最小长度的原因。

    但还有一点更重要。 Java long 总是有符号的,所以即使是行

    System.out.print(1L << 63);
    

    会给出一个负数。在二进制补码下,只要最左边的位为 1,则该数字为负数。

    您实际上不能在 Java 原始类型中表示数字 263 = 9223372036854775808,因为该数字大于最大 long,而 long 是最大的原始类型。不过,您可以将此号码表示为BigInteger。您甚至可以使用代码通过左移 63 来生成它

    BigInteger.ONE.shiftLeft(63)
    

    【讨论】:

    • +1 以获得很好的答案,其中还包括实用的解决方案。 p.s.我希望你不介意我冒昧地将 2^63 编辑成更具可读性的内容。
    • 当然,您可以将 2^63 表示为 long,有些操作会解释为负数,但对于大多数数学符号而言,这是无关紧要的。
    【解决方案2】:

    你有一个integer overflow [两次]。

    1 << 32 == 1
    1 << 31 == -2147483648 [ becuase this is the binary representation in 2's complement for -2147483648]
    1 << 63 == 1 << (32 + 31) == (1 << 32) << 31 == 1 << 31 == -2147483648
    

    当您执行(long)(1 &lt;&lt; (63)) 时,您只是将1 &lt;&lt; (63) [即-2147483648] 的结果转换为long - 它不会改变它的值。

    【讨论】:

    • 感谢您指出和描述溢出!我一直在寻找对 OpenJDK 的 BitSet 实现中的代码的解释: [ long firstWordMask = WORD_MASK >> -toIndex; ] 即使在这种情况下 WORD_MASK 很长。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    相关资源
    最近更新 更多