2014-02-27 72 views
2

對於這個代碼段浮點加法和除法

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

我想知道什麼部分(IEEE 754)將導致計數3:爲1.0,而不是0.9999999999999999。我意識到一般原因會由於二進制數字的數目無限而變爲四捨五入,但如果有人可以更詳細地解釋(IEEE 754)背後的細節,我將不勝感激。

+0

你在尋找什麼樣的細節?你似乎已經很好地總結了它。 –

+0

我想我很想知道他們是否是這種事件的直接術語,因爲我不確定我的教授會接受我的推理,爲什麼事實證明這只是1.0,當我唯一的答案是「因爲四捨五入」。 – user3361646

+1

我不相信IEEE-754保證這樣的代碼永遠都不會成功。第一次,在大多數現代平臺上,它可能不會(至少在一般情況下 - 它可能與某些特定的因數),但我想如果讓它運行足夠長的時間,幾次繞過無窮大後,它可能設法打出正確的位模式,儘管... – twalberg

回答

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。

然而,改變n7結果:

0 
0.142857142857142849212692681248881854116916656494140625 
0.28571428571428569842538536249776370823383331298828125 
0.428571428571428547638078043746645562350749969482421875 
0.5714285714285713968507707249955274164676666259765625 
0.7142857142857141905523121749865822494029998779296875 
0.8571428571428569842538536249776370823383331298828125 
0.9999999999999997779553950749686919152736663818359375 

運行修改,添加1.0/7原計劃將導致一個無限循環。 count會增加,直到它變得如此之大以至於添加1.0/7將舍入舊值,然後停留在該值。

+0

它也不能保證乘法。試試'1.0/49 * 49'。 – dan04

+0

@ dan04確實。通常最好假設舍入誤差,並注意幾個肯定是確切的特殊情況。 –