四舍五入陌生

Пав*_*вел 1 java floating-point double floor

它可能是在深夜,但我无法理解这段代码的行为:

public class DT {
static void theTest(double d){
    double e = Math.floor(d/1630)*1630;
    System.out.println(e-d);
}

public static void main(String[] args) {
    theTest(2*1630);
    theTest(2*1631);
    theTest(2*1629);
    theTest(8.989779443802325E18);
}
Run Code Online (Sandbox Code Playgroud)

}

在我的undertangind中,所有4个案例都应该是非正面的,即"e"总是<="d",但我得到以下输出:

0.0
-2.0
-1628.0
1024.0
Run Code Online (Sandbox Code Playgroud)

为什么??.因为这与FastMath相同,我怀疑是双重特定的?但有人可以解释我这个吗?

Daw*_*ica 5

当你获得大量数据时,双打的间隔比整数更宽.在此范围内进行除法时,可以向上或向下舍入结果.所以在你的第四个测试用例中,除法的结果d/1630实际上是四舍五入到最接近的可用双精度.由于这是一个整数,所以调用floor不会改变它.1630然后将它乘以得到的结果大于d.

编辑

这个效果在2 ^ 52时开始.一旦你超过2 ^ 52,就没有更多的非整数双打.在2 ^ 52和2 ^ 53之间,双精度只是整数.在2 ^ 53以上,双精度比整数间隔更宽.

问题中划分的结果5515202112762162.576... 是在2 ^ 52和2 ^ 53之间.它四舍五入到最接近的double,它与最接近的整数相同,即5515202112762163.现在,floor不会更改此数字,乘以1630得到的结果大于d.

总而言之,我猜这个答案的第一句话有点误导 - 你不需要双倍的间隔比这个效果的整数广泛; 你只需要它们至少与整数一样宽.

如果值d介于0和2 ^ 52*1630之间,则问题中的程序将永远不会输出正数.