216

I have a question about JUnit assertEquals to test double values. Reading the API doc I can see:

@Deprecated
public static void assertEquals(double expected, double actual)

Deprecated. Use assertEquals(double expected, double actual, double delta) instead.

(Note: in older documentation versions, the delta parameter is called epsilon)

What does the delta (or epsilon) parameter mean?

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Édipo Féderle
  • 4,169
  • 5
  • 31
  • 35

8 Answers8

233

Epsilon is the value that the 2 numbers can be off by. So it will assert to true as long as Math.abs(expected - actual) <= epsilon

Grim
  • 1,938
  • 10
  • 56
  • 123
jberg
  • 4,758
  • 2
  • 20
  • 15
  • 4
    So what value should I pass as epsilon? – emeraldhieu Jul 09 '15 at 08:50
  • 21
    @Emerald214 the amount of precision. If you want to assert that a double value is 0D epsilon would be 0 (100% accuracy, no exceptions). If you want a margin of error (say for degrees) you could set epsilon to 1 meaning that, for example, 64.2° is the same as 64.8° (since abs(64.8-64.2) < 1) – Pieter De Bie Sep 25 '15 at 08:14
  • 3
    The documentation says, _"delta - the maximum delta between expected and actual for which both numbers are still considered equal."_ So I think that should be a `<=` not `<`. – Andrew Cheong Apr 16 '18 at 17:00
  • Looking at the code, I see it calls the method `doubleIsDifferent` (for comparing double values) and it returns `Math.abs(d1 - d2) > delta`. So if the difference between d1 and d2 is higher than delta, that means the values are different and will return true. It will return false if the values are considered equals. That method is called in the assertEquals dirrectly and if it returns true, the assertEquals will call `failNotEquals` and the result of the test will be a failure. – anthomaxcool Jun 11 '18 at 17:33
  • 2
    @jbert Can someone advise what a typical epsilon double value would be if I were just working with averaging a lot of numbers or doing standard deviations? – simgineer Mar 23 '19 at 19:24
  • 1
    The epsilon you want to use depends on how large the numbers in your calculations may be and N, the number of operations you do. The Math.ulp() function tells you what accuracy you may hope for. You may try: double epsilon = Math.ulp((double)Integer.MAX_VALUE) * Math.sqrt(N); – Martin Vatshelle Sep 05 '20 at 22:01
135

Which version of JUnit is this? I've only ever seen delta, not epsilon - but that's a side issue!

From the JUnit javadoc:

delta - the maximum delta between expected and actual for which both numbers are still considered equal.

It's probably overkill, but I typically use a really small number, e.g.

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

If you're using hamcrest assertions, you can just use the standard equalTo() with two doubles (it doesn't use a delta). However if you want a delta, you can just use closeTo() (see javadoc), e.g.

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertThat(123.456, equalTo(123.456));
    assertThat(123.456, closeTo(123.456, DELTA));
}

FYI the upcoming JUnit 5 will also make delta optional when calling assertEquals() with two doubles. The implementation (if you're interested) is:

private static boolean doublesAreEqual(double value1, double value2) {
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}
James Bassett
  • 9,458
  • 4
  • 35
  • 68
59

Floating point calculations are not exact - there is often round-off errors, and errors due to representation. (For example, 0.1 cannot be exactly represented in binary floating point.)

Because of this, directly comparing two floating point values for equality is usually not a good idea, because they can be different by a small amount, depending upon how they were computed.

The "delta", as it's called in the JUnit javadocs, describes the amount of difference you can tolerate in the values for them to be still considered equal. The size of this value is entirely dependent upon the values you're comparing. When comparing doubles, I typically use the expected value divided by 10^6.

Steven P.
  • 941
  • 5
  • 15
mdma
  • 56,943
  • 12
  • 94
  • 128
13

The thing is that two double may not be exactly equal due to precision issues inherent to floating point numbers. With this delta value you can control the evaluation of equality based on a error factor.

Also some floating-point values can have special values like NAN and -Infinity/+Infinity which can influence results.

If you really intend to compare that two doubles are exactly equal it is best compare them as an long representation

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

Or

Assert.assertEquals(0, Double.compareTo(expected, result));

Which can take these nuances into account.

I have not delved into the Assert method in question, but I can only assume the previous was deprecated for this kind of issues and the new one does take them into account.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
2

Note that if you're not doing math, there's nothing wrong with asserting exact floating point values. For instance:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

In this case, you want to make sure it's really MIN_VALUE, not zero or -MIN_VALUE or MIN_NORMAL or some other very small value. You can say

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

but this will get you a deprecation warning. To avoid that, you can call assertEquals(Object, Object) instead:

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

And, if you really want to look clever:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

Or you can just use Hamcrest fluent-style assertions:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

If the value you're checking does come from doing some math, though, use the epsilon.

David Moles
  • 48,006
  • 27
  • 136
  • 235
2

Epsilon is a difference between expected and actual values which you can accept thinking they are equal. You can set .1 for example.

Constantiner
  • 14,231
  • 4
  • 27
  • 34
1

I just want to mention the great AssertJ library. It's my go to assertion library for JUnit 4 and 5 and also solves this problem elegantly:

assertThat(actual).isCloseTo(expectedDouble, within(delta))
Tim Büthe
  • 62,884
  • 17
  • 92
  • 129
-6
Assert.assertTrue(Math.abs(actual-expected) == 0)
Prakash
  • 7,794
  • 4
  • 48
  • 44
  • 1
    When using floating point numbers (like float or double), this is not going to work reliably. You may want to review how floating point numbers in java are stored and how the arithmetic operations work on them. (spoiler: expect some rounding errors!) – Attila Mar 20 '20 at 14:42