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?

[465 byte] By [_.-BasY-._a] at [2007-11-27 11:04:12]
# 1

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

_.-BasY-._a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 2

Why do you expect 'true' when it's plainly visible that 0.30000000000000004 is not 0.3?

georgemca at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 3

http://docs.sun.com/source/806-3568/ncg_goldberg.html

sabre150a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 4

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 > top of Java-index,Java Essentials,Java Programming...
# 5

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....

_.-BasY-._a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 6

Thank you.... Something like that article i was looking for, thankx..

_.-BasY-._a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 7

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?

_.-BasY-._a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 8

> 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.

~

yawmarka at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 9

DELTA? Surely, you mean EPSILON? ;-)

thomas.behra at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 10

> DELTA? Surely, you mean EPSILON? ;-)

No, man, I'm always a letter behind.

~Xawmark

:o)

yawmarka at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 11

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...

_.-BasY-._a at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...
# 12

> 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.

~

yawmarka at 2007-7-29 12:56:29 > top of Java-index,Java Essentials,Java Programming...