5

Possible Duplicate:
Manipulating and comparing floating points in java

Am I supposed to use an Epsilon while comparing floating point numbers in Java ? Does the Float.compare(float f1, float f2) static method is safe to use ?

Thanks !

EDIT : I think I got it.

When I write, let's say, 3.6f in eclipse, the compilator interpret this number as 3.6. However, when I write 1.2f * 3.0f, the result is 3.6000001. While mathematically this is false, these two results are obviously inequals. Hence the need to have an epsilon while checking equality.

However, when I write 0.0f in eclipse, the compilator interpret this as 0 strictly, because IEEE 754 is able to handle it correctly. Therefore, ensuring a float is strictly positive with (value > 0.0f) is correct.

The only problem I see is when the computer doesn't use IEEE 754 representation, and instead use a representation which doesn't handle 0 correctly.

Am I right ?

Community
  • 1
  • 1
Klems
  • 183
  • 1
  • 2
  • 8
  • 1
    The answer depends on what you're trying to do. In fact, whether you should be using floating point or not also depends on it. Explain the problem at hand, only then will you get a useful answer. – Matti Virkkunen May 07 '11 at 20:07
  • Safe in what way? It is a handy method and can handle some edge cases, but it won't prevent you or me from creating our own bugs. Also, I've used an epsilon when trying to implement my own equals method for floating point numbers, but not when comparing them. – Hovercraft Full Of Eels May 07 '11 at 20:07
  • Sorry for not being specific enough. I'm writing particles for a game. I want to know when deltaTime (float) is equal to 0.0, because I compute speed using velocity = distance * (1 / deltaTime). Having an infinite speed is a bit silly. Right now I use (Float.compare(deltaTime, 0.0f) != 0) to ensure the deltaTime is more than 0.0. The deltaTime CAN'T be less than 0. – Klems May 07 '11 at 20:23
  • How bad are you results if it's equal to 10^-20? How 'bout 10^-30? Still think that your only concern is negative time? – duffymo May 07 '11 at 20:25
  • I meant I CAN'T have a negative time. It is totally impossible. I want to know when deltaTime is strictly superior to 0, and Float.compare seem to do the trick. If I just want to know when a float is strictly positive, I could use (deltaTime > 0.0), right ? – Klems May 07 '11 at 20:47

2 Answers2

14

Math.ulp() method has a practical use in testing. As you undoubtedly know, you should usually not compare floating-point numbers for exact equality. Instead, you check that they are equal within a certain tolerance. For example, in JUnit you compare expected to actual floating-point values like so:

assertEquals(expectedValue, actualValue, 0.02);

This asserts that the actual value is within 0.02 of the expected value. However is 0.02 a reasonable tolerance? If the expected value is 10.5 or -107.82, then 0.02 is probably fine. However, if the expected value is several billion, then the 0.02 may be completely indistinguishable from zero. Often what you should test is the relative error in terms of ULPs. Depending on how much accuracy the calculation requires, you usually select a tolerance somewhere between 1 and 10 ULPs. For example, here I specify that the actual result needs to be within 5 ULPs of the true value:

assertEquals(expectedValue, actualValue, 5*Math.ulp(expectedValue));

http://www.ibm.com/developerworks/java/library/j-math2/index.html

Marek Sebera
  • 39,650
  • 37
  • 158
  • 244
  • 1
    What if one value is big and the other small ? Is taking the ULP of the sum a good idea ? – Winter May 16 '17 at 16:51
4

Yes, it's advisable to use a tolerance to check the absolute value of the difference between two floating point numbers.

Compare tells you if one double is less than, equal to, or greater than another. It won't tell you how close they are to one another, so, no, it's no safer than comparing with ==.

aioobe
  • 413,195
  • 112
  • 811
  • 826
duffymo
  • 305,152
  • 44
  • 369
  • 561