Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Assert Two doubles in JUnit Using assertEquals with Epsilon?

Tags:

java

junit

assertEquals for doubles is deprecated. I found that the form with Epsilon should be used. It is because of impossible 100% strictness of doubles. But anyway I need to compare two doubles (expected and actual result), but I don't know how to do it.

At the moment my test looks like:

@Test
public void testCalcPossibleDistancePercentageCount() {
    int percentage = 100;
    assertEquals("Wrong max possible value for %" + percentage, 110.42, processor.calcPossibleValue(percentage));
    percentage = 75;
    /*corresponding assertions*/
}

Here are 3 double values I receive and which I want to check with JUnit: 110.42, 2760.5 and 10931.58. How should JUnit test look like with assertions for them? I receive them as a result of calculation in a method:

processor.calcPossibleValue(allowed_percentage){return /*Some weird formulae here*/;}
like image 227
Dragon Avatar asked Dec 15 '22 21:12

Dragon


2 Answers

You need to add a fourth parameter to the assertEquals call: the threshold within which two doubles should be considered "equal". Your call should look like this:

assertEquals("Wrong max possible value for %" + percentage, 110.42,
        processor.calcPossibleValue(percentage), 0.01);

The above call would indicate that if the value returned by processor.calcPossibleValue(percentage) is within ± 0.01 of 110.42, then the two values are considered equal. You can change this value to make it as small as is necessary for your application.

See the JUnit documentation for more information.

like image 101
Jon Newmuis Avatar answered Jan 12 '23 00:01

Jon Newmuis


A Java double uses the IEEE 754 64-bit format. This format has 52 mantissa bits. When comparing 2 values the epsilon should take into account the magnitude of the expected value.

For example, 0.01 might work okay for 110.42 however it won't work if the expected value is > 252. The magnitude of 252 is so large that 0.01 would be lost due to precision (i.e. only 52-bit mantissa bits). For example, 252 + 0.01 == 252.

With that in mind, epsilon should be scaled to the expected value. For example, expected value ÷ 252 - 3 or 110.42 ÷ 252 - 3 = 1.96... x 10-13. I chose 252 - 3 since this will give a tolerance in the 3 least significant bits in the mantissa.

One caution is that if the expected value is 0.0 then this formula computes epsilon as 0.0 which may be too strict for a particular case.

Another caution is that NaN and ±∞ are not handled.

like image 41
Nathan Avatar answered Jan 12 '23 00:01

Nathan