java - 四舍五入的双重陌生感

标签 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);
}

在我的理解中,所有 4 种情况都应该是非阳性的,即“e”总是<=“d”, 但我确实得到了以下输出:

0.0
-2.0
-1628.0
1024.0

为什么??。 因为这与 FastMath 相同,我怀疑某些双重特定的东西?但是谁能给我解释一下?

最佳答案

当你得到很大的数字时, double 比整数的间距更宽。当您在此范围内进行除法时,结果可以向上或向下舍入。因此,在您的第四个测试用例中,除法 d/1630 的结果实际上四舍五入到最接近的可用 double 值。因为这是一个整数,所以调用 floor 不会改变它。将它乘以 1630 得到的结果大于 d

编辑

此效果在 2^52 时开始。一旦超过 2^52,就不再有非整数 double 。在 2^52 和 2^53 之间, double 只是整数。在 2^53 以上, double 比整数间距更宽。

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

总而言之,我猜答案的第一句话有点误导 - 您不需要 double 的间距比整数更宽以产生这种效果;您只需要它们的间距至少与整数一样

d 的值在 0 到 2^52 * 1630 之间,问题中的程序永远不会输出正数。

关于java - 四舍五入的双重陌生感,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24599498/

相关文章:

java - 在 JavaFX 中向 GridPane 添加标签时遇到问题

java - Android 选项卡式 View 在触摸之前不会更新

java ->> 在 Java 中做什么?

c++ - 如何确定 float, double 的有效位宽度 : Is there a standard definition?

c# - 表达式和分配的对象之间的浮点不一致

c - 为什么 printf("%.6g, <value>) 忽略小数点后的零?

C 如何从无符号整数中检索精确的 double 值(精度)

java - 有什么办法可以代替动态方法吗?

python - 在 Python3 中打印格式化的浮点列表

c++ - 从内存中提取 double 的字节值