user3086472
user3086472

Reputation: 41

working decimal point numbers

I wrote a program in java about floating point but the output obtained is not an accurate one; whereas the same program written in C did produce an accurate result.

Code Snippet:

public class One {

public static void main(String...args){

    double i, num=0.0;
    for(i=0;i<10;i++)
    num=num+0.1;
    System.out.println(num);

    }
}

output: 0.9999999999999999

The program in C goes like this

#include<stdio.h>
main()
{

double i,num=0.0;
for(i=0;i<10;i++)
num=num+0.1;

printf("%f",num);

}

output:1.00000

What am I doing wrong?

Upvotes: 4

Views: 144

Answers (5)

Ved
Ved

Reputation: 369

There is a strictfp keyword, like:

strictfp class Example
{
    //your code here
}

strictfp is a keyword introduced in Java SE 2(or somewhere near that) as the floating point model was relaxed a little.

Upvotes: 0

Richard Tingle
Richard Tingle

Reputation: 17226

C is hiding the problem not removing it

The idea that the C program is more accurate is a misunderstanding of what is happening. Both have imprecise answers but then by default C has rounded to 6 significant figures. Hiding the tiny error. Were you to actually use the value in a calculation (for example num==1) you'd find that both are inaccurate.

Usually it doesn't matter for well written programs

In general intelligently written programs can cope with this tiny error without difficulty. For example your program can be rewritten to recreate a double each time

double i, num=0.0;
for(i=0;i<10;i++)
   num=0.1*i;
   System.out.println(num);

}

Meaning that the error does not grow. Additionally you should never use == with doubles as the tiny inaccuracy can be visible there.

In the very very occasional occurrences where this tiny error is a problem (currency programs being the most common); bigDecimal can be used.

This isn't a problem with floating point numbers but with the conversion from base 10 to base 2.

There are fractions in base 10 that cannot be expressed exactly; for example 1/3. Similarly there are fractions that cannot be expressed exactly within binary for example 1/10. It is from this perspective that you should look at this

The problem in this case was that when you wrote "0.1", a base 10 number the computer had to convert that to a binary number, 0.1=(binary)0.00011001100110011001100110011001....... forever but because it couldn't exactly represent that in binary with the space it had it ended up as (binary)0.0001100110011001. A binary friendly number (such as 1/2) would be completely accurate until the double ran out of precision digits (at which point even binary friendly numbers couldn't be exactly represented)

1 number of decimal places not accurate

Upvotes: 5

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35547

This is an issue in floating number representation. use BigDecimal

You can understand the issue here. if you run following code,

    double i, num=0.0;
    for(i=0;i<10;i++) {
        System.out.println(num);
        num=num+0.1;
    }
    System.out.println(num);

Out put

0.0
0.1
0.2
0.30000000000000004 // wrong value, it should be 0.3
0.4
0.5
0.6
0.7
0.7999999999999999 // this one should be 0.7+0.1=0.8
0.8999999999999999 // this should be 0.8+0.1=0.9
0.9999999999999999 // final result should be 0.9+0.1=1

Let's try with BigDeciaml

 double i;
 BigDecimal num=BigDecimal.ZERO;
 for(i=0;i<10;i++) {
     System.out.println(num);
     num=num.add(new BigDecimal("0.1"));
   }
 System.out.println(num);

Out put

0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0

Upvotes: 0

mbatchkarov
mbatchkarov

Reputation: 16039

The problem is not with Java, but about how computers represent floating point numbers in binary. Some numbers are impossible to represent exactly, so you get a little bit of rounding error as you add 0.1. I suggest you read this great article for a detailed explanation. Also, there are algorithms specifically designed to minimise error when adding a sequence of numbers.

Upvotes: 1

Andrei Nicusan
Andrei Nicusan

Reputation: 4623

Try using BigDecimal. Floating point number representation is an old moot point of Java (and not only).

double i;
BigDecimal num = BigDecimal.ZERO;
for(i=0;i<10;i++)
    num = num.add(new BigDecimal("0.1"));
System.out.println(num);

Upvotes: 2

Related Questions