Skip to main content
5 of 5
added 1 character in body
Spotted
  • 599
  • 2
  • 9

Another small concern (more programing than mathematic) about FLOAT_TOLERANCEand DOUBLE_TOLERANCE:

  • If the outside world of Numbers need to know these values, make them final (avoiding someone to modify them and altering the rightness of future numbers comparisons)
  • Otherwise, make them just private

Update


public class Numbers {

    /**
     * The tolerance value for comparing the {@code float} values.
     */
    public static final float FLOAT_TOLERANCE = 5E-8f;
    /**
     * The tolerance value for comparing the {@code double} values.
     */
    public static final double DOUBLE_TOLERANCE = 5E-16;

    ...

    /**
     * Returns {@code true} if the arguments are <i>approximately</i> equal. The default delta used for comparisons is {@value #FLOAT_TOLERANCE}.
     *
     * @param floats The arguments to check.
     * @return {@code true} if the arguments are <i>approximately</i> equal.
     */
    public static boolean areEquals(float... floats) {
        return areEqual(FLOAT_TOLERANCE, floats);
    }

    /**
     * Returns {@code true} if the arguments are <i>approximately</i> equal.
     *
     * @param tolerance The delta for comparisons.
     * @param floats The arguments to check.
     * @return {@code true} if the arguments are <i>approximately</i> equal.
     */
    public static boolean areEqual(float tolerance, float... floats) {
        int length = floats.length;
        checkLength(length);
        float d = floats[0];
        for (int i = 1; i < length; i++) {
            if (!areEqual_impl(tolerance, d, floats[i])) {
                return false;
            }
        }
        return true;
    }

    private static boolean areEqual_impl(float tolerance, float f1, float f2) {
        // the corner cases first:
        if (Float.isNaN(f1) && Float.isNaN(f2)) {
            return true;
        }
        if (Float.isInfinite(f1) || Float.isInfinite(f2)) {
            return f1 == f2;
        }
        float abs;
        if (f1 == f2 || (abs = Math.abs(f1 - f2)) <= tolerance) {
            return true;
        }
        // compare using the larger ulp
        float ulp1 = Math.ulp(f1);
        float ulp2 = Math.ulp(f2);
        return abs <= (ulp1 > ulp2 ? ulp1 : ulp2);
    }

    //Same principle for double

}
Spotted
  • 599
  • 2
  • 9