public static boolean almostEqual(double a, double b, double eps){
    return Math.abs(a-b)<eps;
}

Where eps is measure of equality.

Answer from Ano on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › java numbers › comparing doubles in java
Comparing Doubles in Java | Baeldung
December 11, 2025 - The recommended algorithm to compare double values in plain Java is a threshold comparison method. In this case, we need to check whether the difference between both numbers is within the specified tolerance, commonly called epsilon:
🌐
Medium
medium.com › @AlexanderObregon › javas-double-compare-method-explained-6159db37e326
Java’s Double.compare() Method Explained | Medium
December 23, 2024 - For instance, in a dataset, you might replace NaN with a custom object or a mapping for clearer identification. Although Double.compare() offers precise ordering, it does not account for tolerance thresholds often needed in numerical comparisons.
🌐
Guava
guava.dev › releases › 17.0 › api › docs › com › google › common › math › DoubleMath.html
DoubleMath (Guava: Google Core Libraries for Java 17.0 API)
Technically speaking, this is equivalent to Math.abs(a - b) <= tolerance || Double.valueOf(a).equals(Double.valueOf(b)). ... All NaNs are fuzzily equal. If a == b, then a and b are always fuzzily equal. Positive and negative zero are always fuzzily equal. If tolerance is zero, and neither a nor b is NaN, then a and b are fuzzily equal if and only if a == b. With Double.POSITIVE_INFINITY tolerance, all non-NaN values are fuzzily equal...
Top answer
1 of 3
8
  1. Please make the class final to let noone inherit the class.
    1. Nobody would expect a AsserationError if he can inherit the class.
    2. Everyone who inherit the class would have duplicate javadoc.
  2. Please throw a RuntimeException or an IllegalStateException because the javadoc matches better.
  3. ;P let me miss seriousness.
  4. i miss strictfp at the class definition because the math-processor may wrong.
  5. getFloatTolerance you dont need the getter. If it would be a bean, you need it but it is no bean.
  6. setFloatTolerance throws a IAE, but this behaviour is not part of the javadoc, and if you add this behaviour to the javadoc you shall write the signature of the method matching to the javadoc. assertProperLength should be have the correct javadoc and signature too (including the pending methods).
  7. The classname Numbers should be named "NumberHelper".
  8. The above code runs without resulting in any assertion errors. (Yipee!!), Yipee but wait ... did you run it as JUnit-Tests or activated the -ea by manual?
  9. Some methods needs to have javadoc.

I have a few more but ill stop here because this class is not thread-save.

2 of 3
3

Generic methods

You can use generic methods for something like this. Rather than having to type out methods for each individual integer type, you can use a generic method for your areEqual methods, like this:

public static <TNumber> boolean areEqual(TNumber... numbers) {
    int length = numbers.length;
    assertProperLength(length);
    TNumber d = numbers[0];        
    for (int i = 1; i < length; i++) {
        if (!d.equals(numbers[i])) {
            return false;
        }
    }
    return true;
}

This eliminates the need to create duplicate methods for each individual type, and makes your code generally easier to read.

This can also apply to your areEqual overloads with just two arguments. I wasn't quite sure how to implement them in this context, although I'm quite sure you can figure it out. Be sure to use .equal though rather than ==, as areEqual may return false when true is expected.


Nitpicks

Some of your error messages are not so great. For example:

  • "No instances for you! ;P" would be better as "An instance of this class cannot be created.".
  • "Absurd tolerance value." would also be better as "Invalid tolerance value. Tolerance value must be ...".

The error types that you're raising don't make much sense. For example, instead of an IllegalArgumentException, it might make more sense to raise an ArithmeticException.

Top answer
1 of 4
10

1) Don't override equals/hashCode only for unit testing purposes

These methods have a semantic and their semantic is not taking into consideration all fields of the class to make a test assertion possible.

2) Rely on testing library to perform your assertions

Assert(students.contains(expectedStudent)

or that (posted in the John Bollinger answer):

Assert(students.stream().anyMatch(s -> expectedStudent.matches(s)));

are great anti patterns in terms of unit testing.
When an assertion fails, the first thing that you need is knowing the cause of the error to correct the test.
Relying on a boolean to assert the list comparison doesn't allow that at all.
KISS (Keep it simple and stupid): Use testing tools/features to assert and don't reinvent the wheel because these will provide the feedback needed when your test fails.

3) Don't assert double with equals(expected, actual).

To assert double values, unit testing libraries provide a third parameter in the assertion to specify the allowed delta such as :

public static void assertEquals(double expected, double actual, double delta) 

in JUnit 5 (JUnit 4 has a similarly thing).

Or favor BigDecimal to double/float that is more suitable for this kind of comparison.

But it will not completely solve your requirement as you need to assert multiple fields of your actual object. Using a loop to do that is clearly not a fine solution.
Matcher libraries provide a meaningful and elegant way to solve that.

4) Use Matcher libraries to perform assertions on specific properties of objects of the actual List

With AssertJ :

//GIVEN
...

//WHEN
List<Student> students = getStudents();

//THEN
Assertions.assertThat(students)
           // 0.1 allowed delta for the double value
          .usingComparatorForType(new DoubleComparator(0.1), Double.class) 
          .extracting(Student::getId, Student::getName, Student::getGpa)
          .containsExactly(tuple(1234, "Peter Smith", 3.89),
                           tuple(...),
          );

Some explanations (all of these are AssertJ features) :

  • usingComparatorForType() allows to set a specific comparator for the given type of elements or their fields.

  • DoubleComparator is a AssertJ comparator providing the facility to take an epsilon into consideration in the double comparison.

  • extracting defines values to assert from the instances contained in the List.

  • containsExactly() asserts that the extracted values are exactly (that is no more, no less and in the exact order) these defined in the Tuples.

2 of 4
4

The behavior of List.contains() is defined in terms of the equals() methods of the elements. Therefore, if your Student.equals() method compares gpas for exact equality and you cannot change it then List.contains() is not a viable method for your purpose.

And probably Student.equals() shouldn't use a comparison with tolerance, because it's very hard to see how you could make that class's hashCode() method consistent with such an equals() method.

Perhaps what you can do is write an alternative, equals-like method, say "matches()", that contains your fuzzy-comparison logic. You could then test a list for a student fitting your criteria with something like

Assert(students.stream().anyMatch(s -> expectedStudent.matches(s)));

There is an implicit iteration in that, but the same is true of List.contains().

Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 48320900 › efficient-comparison-of-2-double-arrays-with-tolerance-java
Efficient comparison of 2 double arrays with tolerance - Java - Stack Overflow
I wondered if maybe there is some way to do an element wise subtraction of one array from the other, then sum the absolute values in the resulting array and compare that answer to the tolerance. 2018-01-18T12:23:30.927Z+00:00 ... Unfortunately it won't work for you. The minimum iterations you would have to do is O(n). If you try any kind of summing the values and comparing the results you won't have any guarantees. As @Lion Chaga said you have to check for null values as well. 2018-01-18T13:18:26.6Z+00:00 ... Also if you consider replacing the for-loop with streams make sure you do a research on the topic.
🌐
Truth
truth.dev › floating_point.html
Truth for floating point types
The error in representing an arbitrary real number as a double is at most 1 part in ~10^16; in most cases, accumulated error from operations like addition and multiplication will be a small multiple of this (although beware pathological cases such as subtracting two very similar large numbers to get a very small number, which magnifies the relative errors significantly: you should try to avoid these in your code wherever possible anyway). By using a tolerance of 1 part in 10^10 you only risk a false pass if a bug introduces an error into the 10th significant figure of the result, and only risk a false failure if the relative numerical errors are magnified by a factor of ~10^6.
🌐
HowToDoInJava
howtodoinjava.com › home › java examples › correct way to compare floats or doubles in java
Correct way to compare floats or doubles in Java
January 25, 2022 - Let’s learn how to compare float values in Java. Table of Contents 1. Simple comparison [Not recommended] 2. Threshold based comparison [Recommended] 3. Compare with BigDecimal [Recommended] First look at the simple comparison to understand what exactly is wrong with comparing double with == operator.
🌐
Alvin Alexander
alvinalexander.com › source-code › java-approximately-equals-method-function
A Java “approximately equal” method (function) | alvinalexander.com
February 8, 2017 - As a quick note, here’s the source ... in an Android application: /** * determine whether two numbers are "approximately equal" by seeing if they * are within a certain "tolerance percentage," with `tolerancePercentage` given * as a percentage (such as 10.0 meaning "10%...
🌐
GeeksforGeeks
geeksforgeeks.org › java › double-compare-method-in-java-with-examples
Double compare() Method in Java with Examples - GeeksforGeeks
July 11, 2025 - The compare() method of Double Class is a built-in method in Java that compares the two specified double values.
🌐
@ankurm
ankurm.com › home › why you should never use == to compare floats and doubles in java
Why You Should Never Use == to Compare Floats and Doubles in Java
November 5, 2025 - Never use the == operator to compare float or double values for equality. Always use a tolerance-based comparison (epsilon) to check if the numbers are close enough for your specific needs. By understanding the nature of floating-point arithmetic and adopting this best practice, you’ll write ...
🌐
LabEx
labex.io › tutorials › java-how-to-compare-two-floating-point-numbers-in-java-413955
How to compare two floating-point numbers in Java | LabEx
double a = 0.1; double b = 0.2; ... can be useful when the values being compared are very small. Java provides the Double.compare() method, which compares two double values numerically....
🌐
Delft Stack
delftstack.com › home › howto › java › compare doubles in java
How to Compare Doubles in Java | Delft Stack
March 11, 2025 - In this code, we utilize Double.compare(a, b), which returns 0 if a is equal to b, a value less than 0 if a is less than b, and a value greater than 0 if a is greater than b. This method is concise and effectively avoids the pitfalls of direct ...
🌐
DEV Community
dev.to › pavel_polivka › double-comparison-in-java-1b7
Double comparison in Java - DEV Community
May 12, 2021 - Simply, we will subtract those doubles, make absolute value, and compare if the result is smaller than some very small number. double epsilon = 0.000001d; boolean result = Math.abs(firstDouble - secondDouble) < epsilon; System.out.println(result); ...
🌐
JetBrains
jetbrains.com › help › resharper › CompareOfFloatsByEqualityOperator.html
Code inspection: Equality comparison of floating point numbers | ReSharper Documentation
February 11, 2024 - double add = 0; for (int i = 1; ... correctly, we need to specify a tolerance, that is, a value to indicate by how much the result can diverge from the intended value....