java - 奇怪的 Java 行为 : How come adding doubles with EXACTLY two decimal places result to a double with MORE THAN two decimal places?

标签 java

如果我有一个 double 组,每个数组都有两个小数位,通过循环将它们加在一起,然后打印出总数,结果是一个小数点后两位以上的数字。这很奇怪,因为从理论上讲,将两个数字相加,每个数字都有 2 个小数位且只有 2 个小数位,永远不会产生一个超过百分之一的非零数字。

尝试执行这段代码:

double[] d = new double[2000];
for (int i = 0; i < d.length; i++) {
    d[i] = 9.99;
}

double total = 0,00;
for (int i = 0; i < d.length; i++) {
    total += d[i];
    if (("" + total).matches("[0-9]+\\.[0-9]{3,}")) { // if there are 3 or more decimal places in the total
        System.out.println("total: " + total + ", " + i); // print the total and the iteration when it occured
    }
}

在我的电脑上,打印出来的是:

total: 59.940000000000005, 5

如果我将总数四舍五入到小数点后两位,那么我得到的数字与我在计算器上手动将 9.99 相加六次时得到的数字相同。但这是怎么发生的,额外的小数位从何而来?我做错了什么或者(我怀疑这可能)这是一个 Java 错误吗?

最佳答案

您是否熟悉分数从 10 进制到 2 进制的转换(十进制到二进制)?如果没有,请查找。

然后您会发现,虽然 9.99 在 10 进制下看起来很正常,但在二进制中看起来并不那么好;它看起来像一个重复的小数,但是是二进制的。我确定您以前见过循环小数,对吗?它没有结束。但是 Java(或与此相关的任何语言)必须将无限的数字序列保存到有限数量的字节中。那就是额外数字出现的时候。当您将该截断的二进制转换回十进制时,您实际上是在处理一个不同的数字。存储在变量中的数字不完全是 9.99,它类似于 9.9999999991(只是一个例子,我没有计算出数学)。

但是您可能对如何解决这个问题感兴趣,对吧?查找 BigDecimal 类。这就是您要用于计算的内容,尤其是在处理货币时。另外,查看 DecimalFormat,这是一个将数字写成格式正确的字符串的类。例如,当您只想显示 2 个小数位而您的数字有很多时,我认为它会为您四舍五入。

关于java - 奇怪的 Java 行为 : How come adding doubles with EXACTLY two decimal places result to a double with MORE THAN two decimal places?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9906169/

相关文章:

java - Spring 安全示例

java - 正则表达式匹配管道字符第 n 次出现后的子字符串

使用 {} 大括号的 Java String replaceAll() 方法

java - 删除启动 jar 的脚本文件

java - 如何读取 opencsv 中的特定 header ?

java - 在类中实现时保留泛型

java - 分布式计算应用

java - 如何将选定的项目从一个数组复制到另一个数组?

java.lang.IllegalArgumentException : Parameter 'directory' is not a directory 异常

java - Java 中的单例与 C++ 中的单例