繁体   English   中英

对浮点或双精度值执行重复加法会产生意外结果

[英]Performing repeated additions on float or double values produces unexpected results

我在代码中找到了一个but,但是经过一番搜索,我意识到我执行的某些浮动操作产生了错误的结果。 所以我输入了以下循环:

 float f = 0f;
     for(int i =0; i<15; i++){
        f+= 10.1f;
        System.out.println(f);
}

但是在结果中,我得到了意外的其他十进制值:

10.1
20.2
30.300001
40.4
50.5
60.6
70.7
80.799995
90.899994
100.99999
111.09999
121.19999
131.29999
141.4
151.5

这是怎么回事,我该如何预防?

您不能“预防”它。 相反,您需要做的就是期待并补偿。

请参阅: 每位计算机科学家都应了解的浮点运算法则

数字以二进制形式存储,并且以某种精度在二进制和十进制之间的表示并不完美,从而导致“舍入误差”。 如果在这种情况下精度至关重要,请尝试使用BigDecimal代替

您的代码中的两个操作会导致错误:

  • 源文本10.1ffloat的转换。 这种转换是不精确的,因为不能以Java使用的浮点格式精确表示10.1。
  • f先前值加上10.1f 在许多这些加法中,确切的总和将不能完全适合浮点格式,因此必须将结果四舍五入。

您可以修改循环以避免累积错误:

for (int i = 0; i < 15; i++)
{
    f = (i+1) * 101 / 10.f;
    System.out.println(f);
}

+1) in every iteration, but it will be the closest representable value. 当您以这种方式编写代码时,在每次迭代中f仍将不完全是10.1•( +1),但它将是最接近的可表示值。 在此新版本中,精确计算了(i+1) * 101 ,而10.f恰好是10,因为以浮点格式可以表示10。 这意味着唯一的错误在于除法运算。 该操作将返回最接近精确结果的可表示值。

Java使用IEEE-754二进制浮点,浮点数为32位, double float为64位。 在那些格式中,数字基本上表示为整数乘以2的幂。在32位格式中,整数的大小必须小于2 24 可以最接近32位格式的10.1的是5295309•2 -19 ,即10.1000003814697265625。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM