Reputation: 41
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
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
Reputation: 17226
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.
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.
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.000110011001100
1. 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
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
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
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