-1

I am using the following code to populate a Spinner in one of my Activities...

    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 );

I was assuming this would give me a list as follows : 0.0, 0.1, 0.2, 0.3, 0.4, and so on. However, this is what the list looks like when I run my program:

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

any ideas?

JuiCe
  • 4,132
  • 16
  • 68
  • 119
  • possible duplicate of [Moving decimal places over in a double](http://stackoverflow.com/questions/4937402/moving-decimal-places-over-in-a-double) – assylias Jun 26 '12 at 14:20

2 Answers2

5

Use this:

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

The problem is that Double.toString(i) will not round.

The strange values are due to the fact that 0.1 (base 10) does not have an exact representation as a double in Java, so every time you add it to the loop variable, you are adding something a bit different than what you think (if you'll pardon the pun).

The same issue of rounding suggests that you should not be using a double as a loop variable. You are very unlikely to exactly hit your loop limit exactly. I would rewrite your loop as follows:

for( int i = 0; i < 100 ; ++i ) {
    rVoltsList.add( String.format("%.1f", i / 10.0) );
}
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • This works, but I don't understand....if I am only adding 0.1 to the value of i, how does it get those strange values? – JuiCe Jun 26 '12 at 14:21
  • 2
    @JuiCe - The issue is that arithmetic with doubles is generally not exact. In particular, the (base 10) value 0.1 does not have an exact representation in binary. Thus, the last bit or two of the sum will be off. This rounding error often gets worse the more times you add 0.1 to a number. – Ted Hopp Jun 26 '12 at 14:23
  • @JuiCe - Because of the same issue of rounding errors in floating point calculations, you should modify your loop to use an `int` loop variable and computing `i / 10.0` inside the loop. The problem is that you cannot easily predict which side of 10.0 you'll land on in the last iteration (after one hundred additions of not exactly 0.1). From the way you wrote the loop, it looks like you don't want that 9.99999999999999999998 value (after rounding to 10.0). – Ted Hopp Jun 26 '12 at 14:36
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 ) );
}
MAC
  • 15,799
  • 8
  • 54
  • 95
  • If this approach is used, the declaration of `dtime` should be moved out of the loop. There's no need to create a new `DecimalTime` each iteration. – Ted Hopp Jun 26 '12 at 14:27