2016-01-27 86 views
1

我嘗試以下for循環:Java語言對計算不準確嗎?

for(double i = 0.0; i<=0.001; i+=0.0001) 
    System.out.println(i); 

而且我得到以下輸出:

0.0
1.0E-4
2.0E-4
3.0000000000000003E-4
4.0E-4
5.0E-4
6.000000000000001E-4
7.000000000000001E-4
8.000000000000001E-4
9.000000000000002E-4

我的問題是:

  • 如何將這些額外的.000000000000001小號來了嗎?
  • 這些額外的數字總會出現,還是在我的代碼中存在一些問題?
  • 這些錯誤是否僅在Java語言或任何其他編程語言中出現?
  • double適合for環路?
+7

歡迎來到IEEE 754的精彩世界:p – fge

+0

這實際上不是java的錯,但是來自於近似表示IEEE浮點數的小數部分 – BeyelerStudios

+2

*「Java語言對計算不準確?」*> **否**。 *「任何語言的浮點/雙精度計算都不準確」*> **是**。如果您想要更高的精度,請使用[BigDecimal](https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html)。 –

回答

6

不幸的是,並不是所有的號碼可被精確表示在floating point

例如,十進制數0.1未在任何有限精度的二進制 浮點所能表述;確切的二進制 表示將具有連續不斷的「1100」序列:

e = -4; s = 1100110011001100110011001100110011 ...,其中,如前面的 ,s是有效數,e是指數。

當四捨五入到24位時,這變成

e = -4; s = 110011001100110011001101,實際上是十進制的 0.100000001490116119384765625。

+0

有沒有人知道strictfp關鍵詞在哪裏? – HRgiger

+0

看到這篇文章(https://en.wikipedia.org/wiki/Strictfp) – Vlad

+0

thx,哦那不好http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf – HRgiger

1

使用BigDecimal嘗試,這裏是我的示例代碼:

import java.math.BigDecimal; 

public class Test { 

    private static final BigDecimal UPPER_LIMIT = new BigDecimal(0.001); 
    private static final BigDecimal STEPS = new BigDecimal(0.0001); 

    public static void main(String[] args) { 
     for(BigDecimal i = BigDecimal.ZERO; i.compareTo(UPPER_LIMIT) != 1; i = i.add(STEPS)){ 
      System.out.printf("%.4f\n", i); 
     } 

    } 

} 

,輸出是:

0.0000 
0.0001 
0.0002 
0.0003 
0.0004 
0.0005 
0.0006 
0.0007 
0.0008 
0.0009 

附:我沒有花時間進行內存管理和其他細節,應該比使用原語更重的過程