2

Possible Duplicate:
Java floats and doubles, how to avoid that 0.0 + 0.1 + … + 0.1 == 0.9000001?

I am having a following problem in Java - I need to iterate between 0.1f and 1.0f in 0.1f increments,so I would like my output to look like this:

    0.1
    0.2
    0.3
    0.4
    ...
    0.9

Instead,when I do:

for(float i = 0.1f; i < 1f; i += 0.1f)
    System.out.println(i);

I get

0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001

I imagine it has something to do with the way fractions are represented by a computer,but I would like to know why is this,and if there is anything I can do to stop it. thanks.

Community
  • 1
  • 1
gambiting
  • 365
  • 2
  • 9
  • Can you use a double instead? – Esailija Dec 04 '12 at 22:59
  • This is not doable at all, really. There is no exact value `0.1` representable as a float _or_ a double. – Louis Wasserman Dec 04 '12 at 23:00
  • *"I would like to know why is this"* - Short answer is "rounding error". For a long answer, read this - http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. *"... and if there is anything I can do to stop it"* - Short answer "nope". – Stephen C Dec 04 '12 at 23:07

4 Answers4

6

Use integers in your for loop to avoid repeated floating point math, which compounds floating-point errors.

for (int i = 1; i < 10; i++)
{
   float f = (float) i / 10.0f;
   System.err.println(f);
}
rgettman
  • 176,041
  • 30
  • 275
  • 357
2

You could try this:

for(int i = 1; i < 10; i++)
    System.out.println(i/10f);
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9

What you are seeing is a product of inaccuracies that are intrinsic to floats, which naturally build up if you add them continuously, as you do in the code you posted. If we use ints in the loop instead, we avoid the float-addition and, therefore, also the error build-up.

arshajii
  • 127,459
  • 24
  • 238
  • 287
  • I'm not the one who downvoted this answer, but if I were to guess, because your output starts with 0.0, not 0.1. – rgettman Dec 04 '12 at 23:14
  • @rgettman Ah yes - 1 character change, thanks for pointing it out. I really wish downvoters would comment to indicate such things. – arshajii Dec 04 '12 at 23:18
0

floats are binary, and don't represent decimals well

if applicable Iterate in 1/8ths or 0.125 instead.

-2
for(float i =1.0f;i<10f;i+=1f)
System.out.println(i/10f);`

is ugly as hell but works here (Ubuntu AMD64 OpenJDK)

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • 1
    To quote myself: it is ugly as hell, but it works here. – Eugen Rieck Dec 04 '12 at 23:02
  • Hmmm ... looks / sounds like a voodoo solution to me. – Stephen C Dec 04 '12 at 23:04
  • To quote myself: it is ugly as hell, but it works here – Eugen Rieck Dec 04 '12 at 23:04
  • ... provided you keep sacrificing the chickens!! "It seems to work" without a clear understanding of why is a recipe for fragile unmaintainable code. We should be *discouraging* this approach to programming in new programmers ... rather than offering them our own voodoo programming "solutions" to copy into their code. – Stephen C Dec 04 '12 at 23:12
  • Exatlcy. You may substitute cursed ducks, if no chickens are available. This is what I ment by "but works here (Ubuntu AMD64 OpenJDK)": I don't know, if it would work on x86 (and I don't care). The understanding of what happens is trivial: 1/10 is not representable in any binary floating point number, regardless of precision. I don't encourage anybody (experienced or not) to try and make 0.1 an exact float .. it just won't work. What I do say is: This works under the exact circumstances specified. Not a bit more. – Eugen Rieck Dec 05 '12 at 00:18