2012-06-26 85 views
-1

我使用下面的代碼在我的活動之一來填充微調...奇怪雙到字符串的轉換

for(double i = 0; i < 10 ; i+=0.1) { 
     rVoltsList.add(Double.toString(i)); 
    } 
    Spinner rVoltsSpinner = (Spinner) findViewById(R.id.recloseVoltsSpinner); 
    ArrayAdapter<String> rVoltsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, rVoltsList); 
    rVoltsSpinner.setAdapter(rVoltsAdapter); 

我是假設這會給我一個名單如下:0.0,0.1 ,0.2,0.3,0.4等等。 然而,這是列表中的樣子,當我運行我的程序:

0.0 
0.1 
0.2 
0.30000000000000000000000004 
0.4 
0.5 
0.6 
0.7 
0.79999999999999999999 
0.89999999999999999999 
0.99999999999999999999 
1.09999999999999999999 
1.2 
1.3 
and this goes on until 9.99999999999999999998 

什麼想法?

+0

[在上一個雙運動小數]的可能重複(http://stackoverflow.com/questions/4937402/moving-decimal-places-over-in-a -double) – assylias

回答

5

使用此:

rVoltsList.add(String.format("%.1f", i)); 

的問題是,不會圓。

奇怪的值是由於0.1(基數10)在Java中沒有像double那樣的確切表示,所以每次將它添加到循環變量中時,都會添加一些與你認爲(如果你會赦免雙關語)。

舍入的相同問題表明,你不應該使用double作爲循環變量。你不太可能完全達到你的循環限制。我會重寫你的循環如下:

for(int i = 0; i < 100 ; ++i) { 
    rVoltsList.add(String.format("%.1f", i/10.0)); 
} 
+0

這個工程,但我不明白....如果我只加0.1到我的價值,它是如何得到那些奇怪的價值的? – JuiCe

+2

@JuiCe - 問題在於雙打算術一般不準確。特別是,(基數10)值0.1在二進制中沒有精確的表示。因此,總和的最後一位或兩位將關閉。這個舍入誤差通常會在你給一個數字加0.1的時間越多越差。 –

+0

@JuiCe - 由於浮點計算中舍入錯誤的問題相同,因此應該修改循環以在循環內部使用一個int循環變量並計算「i/10.0」。問題在於,你不能輕易預測在最後一次迭代中10.0的哪一側(在不完全增加0.1之後)。從你編寫循環的方式來看,它看起來不像9.99999999999999999998的值(在舍入到10.0之後)。 –

2
DecimalFormat dtime = new DecimalFormat("#.#"); 

for(double i = 0; i < 10 ; i+=0.1) 
{ 
    String i2= Double.valueOf(dtime.format(i)); 
    rVoltsList.add(Double.toString(i2)); 
} 
+2

會不會...... rVoltsList.add(i2); ? – JuiCe

+0

謝謝...... @JuiCe – MAC

+0

如果使用這種方法,'dtime'的聲明應該被移出循環。每次迭代都不需要創建新的「DecimalTime」。 –