java - 为什么使用双重的for循环无法终止

标签 java for-loop floating-point-precision

我正在查看旧的考试问题(目前是大学一年级),我想知道是否有人可以更彻底地解释一下为什么下面的 for 循环不会在它结束时结束应该的。为什么会这样?我知道由于舍入错误或其他原因,它会跳过 100.0,但为什么呢?

for(double i = 0.0; i != 100; i = i +0.1){
    System.out.println(i);
}

最佳答案

数字 0.1 不能用二进制精确表示,就像 1/3 不能用十进制精确表示一样,因此您不能保证:

0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1==1

这是因为在 binary :

0.1=(binary)0.00011001100110011001100110011001....... forever

但是 double 不能包含无限精度,因此,正如我们将 1/3 近似为 0.3333333 一样,二进制表示也必须近似于 0.1。


扩展十进制类比

十进制你可能会发现

1/3+1/3+1/3
=0.333+0.333+0.333
=0.999

这是完全相同的问题。它不应该被视为 float 的弱点,因为我们自己的十进制系统也有同样的困难(但对于不同的数字,使用 base-3 系统的人会觉得我们很难表示 1/3)。然而,这是一个需要注意的问题。

演示

一个 live demo Andrea Ligios 提供的数据显示了这些错误的累积。

关于java - 为什么使用双重的for循环无法终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19907186/

相关文章:

Java 循环缺少给定数组中的元素

c++ - OpenCL 速度和浮点精度

javascript - 如何测试一个 float 是否为整数 "within machine precision"?

java - 如何将数组插入哈希表而无需在 Java 中进行初始化?

c - 在没有for的情况下向左旋转C中的数组?

java - 为什么要序列化模型类

bash - 如何替换文件名中的文本并将文件移动到不同的目录

python - 在 python 2.6 和 python 2.7 上使用随机的不同浮点精度

java - Jackson:JsonBackReference - 无限递归问题

java - 使用spring boot从redis读取字符串