Double trouble
Hi...
Can anybody explain this, please:
public static final void main(String[] args){
for(double i = (double)0.2; i < (double)0.5 ; i += (double)0.1){
System.out.println(i + "," + ((double)0.3 == i));
}
}
Result is:
0.1,false
0.2,false
0.30000000000000004,false< !!!!!!!!!!! EXPECTED TRUE
0.4,false
Is it a problem with procesor CORE 2 DUO?
Anybody know easy fix, please?
Or here is same Float problem:
public static final void main(String[] args){
for(float i = (float)0.5; i < (float)1.0 ; i += (float)0.1){
System.out.println(i + "," + ((float)0.7 == i));
}
}
with result:
0.5,false
0.6,false
0.70000005,false !!!!! EXPECTED TRUE
0.8000001,false
0.9000001,false
Why do you expect 'true' when it's plainly visible that 0.30000000000000004 is not 0.3?
http://docs.sun.com/source/806-3568/ncg_goldberg.html
With floating point numbers you should always compare to a range not equals. The posted article explains the reason. Also, if you search these forums you will find numerous threads on this subject.
jbisha at 2007-7-29 12:56:29 >

I need to fix this problem this way:
0.3 == ROUND(i)
Main problem is that i have very big array of double (100x100x100 members) and i need NOT expensive ROUND() function....
Thank you.... Something like that article i was looking for, thankx..
This solution looks like best performance solution...
public static final double CORECTION = 0.0000001;
public static final boolean EQUALS(double a, double b) {
return a > b - CORECTION && a < b + CORECTION;
}
public static final void main(String[] args){
double[ ][ ] a = new double[10000][10000];
for(int i = 0; i < a.length ; i++){
double tmp = 0.0;
for(int j = 0; j < a.length ; j++){
a[j] = tmp;
tmp+=0.1;
}
}
boolean found = false;
long time = System.currentTimeMillis();
for(int i = 0; i < a.length ; i++){
for(int j = 0; j < a.length ; j++){
if(EQUALS(0.3, a[j])){
found = true;
}
}
}
System.out.println("Time:" + (System.currentTimeMillis() - time) + ":" + found);
found = false;
time = System.currentTimeMillis();
for(int i = 0; i < a.length ; i++){
for(int j = 0; j < a.length ; j++){
if(0.3 == a[j]){
found = true;
}
}
}
System.out.println("Time:" + (System.currentTimeMillis() - time) + ":" + found);
}
Result is:
Time:531:true
Time:344:false
Cycle with EQUALS(0.3, a[j]) has corect "found" value, but elapsed time is almost double than cycle with 0.3 == a[j], but this one doesn't have corect "found" value...
Anybody knows cheaper solution?
> This solution looks like best performance solution...
> Anybody knows cheaper solution?
Better to be slow and correct than fast and wrong, in my opinion. There are always exceptions, of course. Anyway, here's how I'd write it...
static final double DELTA = 0.0000001;
boolean equals(double x, double y) {
return Math.abs(x - y) < DELTA;
}
I haven't tested it for performance.
~
DELTA? Surely, you mean EPSILON? ;-)
> DELTA? Surely, you mean EPSILON? ;-)
No, man, I'm always a letter behind.
~Xawmark
:o)
I do the performance test:
public static final double EPSILON = 0.0000001;
public static final boolean EQUALS1(double a, double b) {
return a > b - EPSILON && a < b + EPSILON;
}
public static final boolean EQUALS2(double a, double b) {
return Math.abs(a - b) < EPSILON;
}
public static final void main(String[] args){
double[][] a = new double[10000][10000];
boolean found;
long time;
for(int i = 0; i < a.length ; i++){
double tmp = 0.0;
for(int j = 0; j < a[i].length ; j++){
a[i][j] = tmp;
tmp+=0.1;
}
}
//////////////////////////////////////////////////////////////////////////////////
found = false;
time = System.currentTimeMillis();
for(int i = 0; i < a.length ; i++){
for(int j = 0; j < a[i].length ; j++){
if(0.3 == a[i][j]){
found = true;
}
}
}
System.out.println(" ==Time:" +
(System.currentTimeMillis() - time) +
":" + (found ? "OK" : "FAIL"));
found = false;
time = System.currentTimeMillis();
for(int i = 0; i < a.length ; i++){
for(int j = 0; j < a[i].length ; j++){
if(EQUALS1(0.3, a[i][j])){
found = true;
}
}
}
System.out.println("EQUALS1: Time:" +
(System.currentTimeMillis() - time) +
":" + (found ? "OK" : "FAIL"));
found = false;
time = System.currentTimeMillis();
for(int i = 0; i < a.length ; i++){
for(int j = 0; j < a[i].length ; j++){
if(EQUALS2(0.3, a[i][j])){
found = true;
}
}
}
System.out.println("EQUALS2: Time:" +
(System.currentTimeMillis() - time) +
":" + (found ? "OK" : "FAIL"));
}
And result was:
==Time:328:FAIL
EQUALS1: Time:484:OK
EQUALS2: Time:1297:OK
EQUALS1 have better performance...
> EQUALS1 have better performance...
Okay, but you should know two things:
1) Your tests are poorly written; and
2) Aside from entertainment value or academic discussion, the results aren't likely to do you much good.
Okay, three things:
3) I'm not at all surprised that using a call to Math.abs() would be slower than comparison using operators only.
~