Math.pow(2,63) - 1 == Math.pow(2,63) - 512为TRUE

Mic*_*ski 3 java double

我觉得这很有趣:

System.out.println(  (long)(Math.pow(2,63) - 1) == Long.MAX_VALUE); // true
System.out.println(  (long)(Math.pow(2,63) - 5) == Long.MAX_VALUE); // true 
System.out.println(  (long)(Math.pow(2,63) - 512) == Long.MAX_VALUE); // true
System.out.println(  (long)(Math.pow(2,63) - 513) == Long.MAX_VALUE); // false
Run Code Online (Sandbox Code Playgroud)

最后三行应该打印false,但实际上只有最后一行,我减去的513给出了正确的答案.

为什么512/513是不准确的突破点?我可以做的唯一连接是512是一千字节的一半.


我知道造成这种情况的原因是由于返回a 而产生的double不准确性Math.pow(int, int)double

我试过这个,java.math.BigInteger这就是我得到的:

BigInteger b = new BigInteger("2");

System.out.println(  (b.pow(63).longValue() - 1) == Long.MAX_VALUE  ); // true
System.out.println(  (b.pow(63).longValue() - 5) == Long.MAX_VALUE  ); // false
System.out.println(  (b.pow(63).longValue() - 512) == Long.MAX_VALUE  ); // false
System.out.println(  (b.pow(63).longValue() - 513) == Long.MAX_VALUE  ); // false
Run Code Online (Sandbox Code Playgroud)

Pat*_*han 7

这是浮点舍入的问题.double实际上有53位有效数,因此在2 ^ 63范围内,连续的双精度数除以1024. 512是你可以减去并且仍然向上舍入的最多.减去513超过下一个双下降的一半,然后向下舍入.

该计划证明了这个问题:

import java.math.BigDecimal;

public class Test
{
  public static void main(String[] args) {
    double maxValue = (double)Long.MAX_VALUE;
    System.out.println(new BigDecimal(maxValue));
    double nextDown = Math.nextAfter(maxValue, 0);
    System.out.println(new BigDecimal(nextDown));
    System.out.println(maxValue-nextDown);
  }
}
Run Code Online (Sandbox Code Playgroud)

它打印:

9223372036854775808
9223372036854774784
1024.0
Run Code Online (Sandbox Code Playgroud)

显示在Long.MAX_VALUE的双倍当量和零方向的下一个双精度之间的1024间隙.