aspose file tools*
The moose likes Java in General and the fly likes Java implementation of Comparing floating point numbers Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Java implementation of Comparing floating point numbers" Watch "Java implementation of Comparing floating point numbers" New topic
Author

Java implementation of Comparing floating point numbers

Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

This is more of an advanced numerical analysis question than about advanced Java....

In Comparison of Floating Point numbers
Bruce Dawson talks about how comparing floats and doubles is a lot harder than it looks.

He describes the problems, and provides some C-language code that does the comparison quickly and correctly.

java.lang.math.IEEEremainder() does something relative to this, but I can't follow exactly what from either the javadocs or chasing references to the real IEEE standad
Bill Shirley
Ranch Hand

Joined: Nov 08, 2007
Posts: 457
Is there a question?

Yes, floating point representation in binary format is a very tricky computer science problem. Comparing floating point numbers is particularly tricky.

Since Java post-dates IEEE 754, I assume is uses that standards comparison methods, but I don't rely on floats or doubles enough to ever bother.


Bill Shirley - bshirley - frazerbilt.com
if (Posts < 30) you.read( JavaRanchFAQ);
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Anybody got an implementation? or URL?
The tricks he uses are only applicable for C, they rely upon pointers and using the same location in memory as both a float and an int. Not possible in Java
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Originally posted by Pat Farrell:
The tricks he uses are only applicable for C, they rely upon pointers and using the same location in memory as both a float and an int. Not possible in Java


Well, there's java.lang.Float.intBitToFloat() and floatToIntBits() and friends; there are analagous methods in the Double class too. These should help satisfy your curiosity, if nothing else.


[Jess in Action][AskingGoodQuestions]
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Originally posted by Ernest Friedman-Hill:
Well, there's java.lang.Float.intBitToFloat() and floatToIntBits() and friends; there are analagous methods in the Double class too. These should help satisfy your curiosity, if nothing else.


Thanks. I'm more than curious, I'm looking for a good implementation. For suitable values of good.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
According to the JLS (S15.16.3) Java's floating point remainder (using the '%' operator) is *different from* the java.lang.Math.IEEEremainder()
function. The operator is based on truncating division while the
function is based on rounding division. You might think that this
won't add up to much, but 8.0 % 3.0 results in -1.0 with rounding
division versus 2.0 with truncating division.


Source: Floating point remainder in Kaffe
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Hi Pat,

OK, I went and looked at the (interesting) linked document. I think you could work from that pretty well, with the following translation: when they have

*(int*)&A

the Java equivalent would be

Float.floatToIntBits(A)

so his final comparison function would be



I did some minimal testing and this seems to work as advertised, but you should probably do more extensive testing.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Thanks, I'll hack arround with your version.

I agree, tt is a fairly interesting question/ problem space
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Originally posted by Ernest Friedman-Hill:


I have done a bit of testing and I don't grok this line. The key, which I couldn't tell until I fired up some test cases and the debugger, is that this comparison is done on the difference of the "integer" values. I have no idea what scale is applicable, ideal, good.

consider these values: ( 0.1F, 0.10000001F)
on my system (intel x86 32 bits) I get a raw difference of 536870912
aka 536,870,912 or 500 million. This fails your assertion test.

I can see that the integer comparison style is a lot faster, but it looks a lot less understandable than the division based relative calculation that the paper says is not good (it has lots of floating abs() etc.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

I've put up some source files, and JUnit tests on my server for others who are interested.
Math java source, Complex, AboutEquals
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Originally posted by Pat Farrell:

consider these values: ( 0.1F, 0.10000001F)
on my system (intel x86 32 bits) I get a raw difference of 536870912
aka 536,870,912 or 500 million. This fails your assertion test.


Hmmm. I don't know how that could be. The answer should be the same on every system, guaranteed by IEEE floating-point standard. On my system this difference is actually 1, which is as it should be.

"ulp" stands for "unit of least precision". A difference of one ulp between two floats indicates that they're "adjacent" floats; that there's no value in between them. If I were using this method I'd probably pass values between 1 and 5 most of the time.

There are ulp(float) and ulp(double) methods in java.lang.Math which show you the absolute magnitude of the difference between a float or double and its nearest neighbor; you should check these out. Based on what I saw here you should find that ulp(0.1) is roughly 0.00000001.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Originally posted by Ernest Friedman-Hill:
Hmmm. I don't know how that could be. The answer should be the same on every system, guaranteed by IEEE floating-point standard. On my system this difference is actually 1, which is as it should be.


Which is one of the reasons I put the code up with URL above
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Reviving an ancient thread since I'm doing more testing in it:


Ernest Friedman-Hill wrote:There are ulp(float) and ulp(double) methods in java.lang.Math which show you the absolute magnitude of the difference between a float or double and its nearest neighbor; you should check these out. Based on what I saw here you should find that ulp(0.1) is roughly 0.000 000 01.


Checking the Math.ulp() functions shows that Dr Friedman-Hill is right.

For floating: f: a: 0.100000, ulpA: 7.45058e-09,
for double: d: a: 0.100000, ulpA: 1.38778e-17,

and for more obscure values, testing one that is 10 ^ -41, which is very close to zero:
d: a: 1.00000e-41, ulpA: 1.27447e-57,

40 more orders of magnitude smaller:
d: a: 1.00000e-81, ulpA: 1.17042e-97,
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Java implementation of Comparing floating point numbers