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

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);

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

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.

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.

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.

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.

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.

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.

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

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,