0

In this loop, I am not getting the value 3.9. It stop at 3.8

for(double a=0.0;a<=3.9; a+=0.1) 
    System.out.println((double) Math.round(a * 10) / 10);

Output:

0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2.0
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
3.0
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
Atri
  • 5,511
  • 5
  • 30
  • 40
vijay velaga
  • 97
  • 1
  • 1
  • 9
  • check now code added – vijay velaga Jan 08 '16 at 06:23
  • 1
    [SMBC - Welcome to the Secret Robot Internet](http://www.smbc-comics.com/?id=2999) – Elliott Frisch Jan 08 '16 at 06:25
  • may be a duplicate, you can check: http://stackoverflow.com/questions/322749/retain-precision-with-double-in-java – hs2345 Jan 08 '16 at 06:34
  • 1
    Shameless plug time! Go to http://www.adambeneschan.com/How-Does-Floating-Point-Work/, type `0.1`, and click Double. The page explains why the value isn't 0.1, but is actually 0.1000000000000000055511151231257827021181583404541015625. If you add this number 39 times, you will get a value that is slightly higher than 3.9, and then `a<=3.9` will be false. – ajb Jan 08 '16 at 06:38
  • a=(double) Math.round(a * 10) / 10; its getting exact value – vijay velaga Jan 08 '16 at 06:42
  • @vijayvelaga `0.1` is a repeating fraction in binary, just like `1/3` is in decimal. 5 is not evenly divisible by 2 (and 0.1 is `1 / (5 * 2)`). – Elliott Frisch Jan 08 '16 at 06:44
  • what is different between two for loops but result not getting same for(double a=1.1;a<=1.4; a+=0.1) { a=(double) Math.round(a * 10) / 10; System.out.println((double) Math.round(a * 10) / 10); } for(double a=0.0;a<=3.9; a+=0.1) { a=(double) Math.round(a * 10) / 10; System.out.println((double) Math.round(a * 10) / 10); } – vijay velaga Jan 08 '16 at 06:56
  • No, `Math.round(a*10)/10` is **not** an exact value. However, when `System.out.println` prints it out, it will round to a certain number of decimal places. From the `Double.toString` javadoc: "How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double." For numbers in this range, this is about 15 places. – ajb Jan 09 '16 at 06:06
  • "what is different between two for loops": In the comment, you're reassigning `a` inside the loop, which you didn't do in your original question. Due to the way things round, and the fact that most of the floating-point numbers you're working with won't be exact, this could result in `a` being changed inside the loop, which seems to result in `a` making it up to some number just below 3.9. – ajb Jan 09 '16 at 06:16

5 Answers5

2

double doesn't have infinite precision, and the number 0.1 isn't precisely representable in binary. Regardless, you could use formatted io and < 4 like

for (double a = 0.0; a < 4; a += 0.1) {
    System.out.printf("%.1f%n", a);
}

which gives the requested output.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

Double arithmetic often doesn't give exact values. Use a BigDecimal, or an Integer divided by 10.

Ken Clubok
  • 1,238
  • 6
  • 11
1

try the following to get a better feel of why your loop is acting the way it is.

double a = 0.0;
for(;a<=3.9; a+=0.1)
  System.out.println(a);
System.out.println(a);

the other way you could go with it would be to change your condition like so. I would warn against this for the simple fact you aren't address the floating point error so much as working around it.

for(double a=0.0;((double)Math.round(a*10)/10) <= 3.9; a+=0.1)
  System.out.println((double) Math.round(a * 10) / 10);
tam
  • 1,583
  • 2
  • 13
  • 25
  • Why do you think that putting `Math.round(a*10)/10` in the `for` loop will work? It might work if you're lucky. But you still won't have an exact value, and you really don't know, without doing some bit twiddling, whether the result will be greater than 3.9 [or whatever `double` 3.9 really evaluates to, since the upper bound won't be exactly 3.9 either]. – ajb Jan 09 '16 at 06:51
0

Double operation has some precision problem. Use BigDecimal operation instead of double than you will get expected result. or compare your variable a in loop with 4 instead of 3.9.

for(double a=0.0;a<=4; a+=0.1)
        System.out.println((double) Math.round(a * 10) / 10);

it will give you desired result.

Zia
  • 1,001
  • 1
  • 13
  • 25
0

The simplest way to make sure things work:

for (int a = 0; a <= 39; a++) {
    System.out.println((double)a/10);
}

In a real-world situation, it's still best to work with integers whenever possible, although BigDecimal may make programs easier to understand when dealing with currency.

ajb
  • 31,309
  • 3
  • 58
  • 84