浮点加法和除法

时间:2014-02-27 19:12:28

标签: loops floating-point floating-point-precision

对于此代码段

double count = 0.0;
while( count != 1.0)
{count += 1.0/3;}

我想知道(IEEE 754)的哪些部分会导致计数3:为1.0而不是.9999999999999999。我意识到由于无限数量的二进制数字,一般的原因将是四舍五入,但如果有人可以详细解释这背后的(IEEE 754)细节,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

没有一般规则可确保添加n 1.0/n份副本会产生1.0。可以通过更改以下程序中的n来探索这一点:

import java.math.BigDecimal;

public class Test {
    public static void main(String[] args) {
        int n = 3;
        double[] counts = new double[n+1];
        for(int i=1; i<counts.length; i++){
            counts[i] = counts[i-1]+1.0/n;
        }
        for(double count : counts){
            System.out.println(new BigDecimal(count));
        }
    }
}

对于n=3,它会打印:

0
0.333333333333333314829616256247390992939472198486328125
0.66666666666666662965923251249478198587894439697265625
1

第一次加法增加为零。第二个添加是简单的加倍,所以它也是准确的。第三次也是最后一次加法涉及四舍五入,但轮次为1.0。添加的确切结果是:

0.999999999999999944488848768742172978818416595458984375

它接近1.0而不是下一个值:

0.99999999999999988897769753748434595763683319091796875

如此圆到最近的几轮到1.0。

但是,将n更改为7会导致:

0
0.142857142857142849212692681248881854116916656494140625
0.28571428571428569842538536249776370823383331298828125
0.428571428571428547638078043746645562350749969482421875
0.5714285714285713968507707249955274164676666259765625
0.7142857142857141905523121749865822494029998779296875
0.8571428571428569842538536249776370823383331298828125
0.9999999999999997779553950749686919152736663818359375

运行修改为添加1.0/7的原始程序会导致无限循环。 count会增加,直到它变得如此之大,以至于添加1.0/7将会转换为旧值,然后停留在该值。