Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Java Float.compare() Always Produce The Correct Result?

This seems like a question that I could easily find an answer for but I couldn't see any entry on this. I know how the floating-point arithmetic works and in order to compare floating numbers I need to use an epsilon check. When I shared this with my team, one of my colleagues asked me this and I couldn't answer.

Does the compare method on Java always produce the correct result, i.e, the result an epsilon check for f1 and f2 would yield?

Float.compare(float f1, float f2);

Note: Especially consider this question for the equality case.

like image 604
Can Bayar Avatar asked Sep 20 '26 10:09

Can Bayar


2 Answers

No, Float.compare does not use any kind of epsilon checking.

Here's for example the OpenJDK 13 implementation of the method:

/**
 * Compares the two specified {@code float} values. The sign
 * of the integer value returned is the same as that of the
 * integer that would be returned by the call:
 * <pre>
 *    new Float(f1).compareTo(new Float(f2))
 * </pre>
 *
 * @param   f1        the first {@code float} to compare.
 * @param   f2        the second {@code float} to compare.
 * @return  the value {@code 0} if {@code f1} is
 *          numerically equal to {@code f2}; a value less than
 *          {@code 0} if {@code f1} is numerically less than
 *          {@code f2}; and a value greater than {@code 0}
 *          if {@code f1} is numerically greater than
 *          {@code f2}.
 * @since 1.4
 */
public static int compare(float f1, float f2) {
    if (f1 < f2)
        return -1;           // Neither val is NaN, thisVal is smaller
    if (f1 > f2)
        return 1;            // Neither val is NaN, thisVal is larger

    // Cannot use floatToRawIntBits because of possibility of NaNs.
    int thisBits    = Float.floatToIntBits(f1);
    int anotherBits = Float.floatToIntBits(f2);

    return (thisBits == anotherBits ?  0 : // Values are equal
            (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
             1));                          // (0.0, -0.0) or (NaN, !NaN)
}

Source

like image 71
ruohola Avatar answered Sep 22 '26 00:09

ruohola


If you read the Javadoc of Float.compare() they talk about "numerically equal". That means that values that represent the same theoretical number, but are differently encoded, are considered equal. Examples are 0.0 == -0.0 and subnormal numbers.

Epsilon checks (where you check if two numbers are within a range of one other, typically a very small number), is not a de-facto standard, and has a lot of practical issues (like which epsilon to choose when you don't know the magnutide of the numbers, or what to do when the two numbers have vastly different magnitudes). Because of that reason, Java only implements exact operations.

like image 44
Mark Jeronimus Avatar answered Sep 21 '26 23:09

Mark Jeronimus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!