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 areEqualareEquals(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 (!areEqualareEqual_impl(tolerance, d, floats[i])) {
return false;
}
}
return true;
}
private static boolean areEqualareEqual_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
}