可能重复:
java for-loop problem
为什么输出以下代码:
for (float j2 = 0.0f; j2 < 10.0f; j2+=0.1f) {
System.out.println(j2);
}
这样:
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
1.0000001
1.1000001
1.2000002
1.3000002
1.4000002
1.5000002
1.6000003
1.7000003
1.8000003
1.9000003
2.0000002
2.1000001
2.2
2.3
2.3999999
2.4999998
2.5999997
2.6999996
2.7999995
2.8999994
2.9999993
3.0999992
3.199999
3.299999
3.399999
3.4999988
3.5999987
3.6999986
3.7999985
3.8999984
3.9999983
4.0999985
4.1999984
4.2999983
4.399998
4.499998
4.599998
4.699998
4.799998
4.8999977
4.9999976
5.0999975
5.1999974
5.2999973
5.399997
5.499997
5.599997
5.699997
5.799997
5.8999968
5.9999967
6.0999966
6.1999965
6.2999964
6.3999963
6.499996
6.599996
6.699996
6.799996
6.899996
6.9999957
7.0999956
7.1999955
7.2999954
7.3999953
7.499995
7.599995
7.699995
7.799995
7.899995
7.9999948
8.099995
8.199995
8.299995
8.399996
8.499996
8.599997
8.699997
8.799997
8.899998
8.999998
9.099998
9.199999
9.299999
9.4
9.5
9.6
9.700001
9.800001
9.900002
还有一个问题:即使我将for循环的条件更改为j2<=10.0f
,输出也是相同的。为什么这样?它不应该在输出中包含10.0
吗?
答案 0 :(得分:5)
正如其他人所提到的,它是关于浮点数的精确度以及每一步操作都可能增加错误的事实。
这就是为什么你从不使用花车代表钱。查看BigDecimal以获得精确的十进制处理。
不包括10.0
的原因是总和已浮动且不再是&lt; = 10.0,因为精度/舍入误差已经漂移到+0.0以上。 9.900002 + 0.1可能会产生类似于10.000002的内容,即&gt; 10.0。
浮点数不表示为精确数字,而是表示为系数和指数,例如(−1)^s × c × b^q
,并且添加到浮点数将结合两个数字的不确定性。由于精度损失,这可能转化为0.70000005而不是0.7。
答案 1 :(得分:4)
double
和float
都有来自计算和表示错误的舍入错误(对于无法准确表示的值)使用float
比使用double
的错误要多得多避免它的一个很好的理由。错误可能大约10 ^ 8倍。
当您打印浮点数时,它将执行少量舍入以隐藏此错误。错误很容易就足够大,可见。
因此,通过定义所需的准确度来自行舍入结果通常是个好主意。
for (float j2 = 0.0f; j2 < 10.05f; j2+=0.1f)
System.out.printf("%.1f ", j2);
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0
您可以使用BigDecimal查看0.1f的精确表示。有趣的是,0.1f
和0.1
的价值不同。
System.out.println("0.1f = " + new BigDecimal(0.1f));
System.out.println("0.1 = " + new BigDecimal(0.1));
System.out.println("0.1f - 0.1 = " + (0.1f - 0.1) + " or " + new BigDecimal(0.1f - 0.1));
打印
0.1f = 0.100000001490116119384765625
0.1 = 0.1000000000000000055511151231257827021181583404541015625
0.1f - 0.1 = 1.4901161138336505E-9 or 1.4901161138336505018742172978818416595458984375E-9
正如已经指出的那样,如果没有合理的舍入,你不能单独使用浮点数(或许多其他目的)。如果代码的性能和可读性不是问题,请改用BigDecimal。
答案 2 :(得分:1)
为什么我的数字,如0.1 + 0.2加起来不是很好的一轮0.3,而且 相反,我得到一个奇怪的结果,如0.30000000000000004?
因为在内部,计算机使用格式(二进制浮点) 它不能准确地表示0.1,0.2或0.3之类的数字。
编译或解释代码时,您的“0.1”已经存在 四舍五入到该格式的最接近的数字,这导致一个小的 甚至在计算发生之前就会出现舍入错误。