Performant way to check java.lang.Double for equality

放肆的年华 提交于 2019-11-29 16:58:34

JUnit has a method of checking a Double for 'equality' with a given delta:

Assert.assertEquals(0.00023d, 0.00029d, 0.0001d);

See this API documentation.

As noted in the comments, JUnit actually most likely is slower than comparing manually with a given delta. JUnit first does a Double.compare(expected, actual) followed (if not equal) by a Math.abs(expected - actual) <= delta.

Hopefully this answer still is useful for people not aware that JUnit actually provides a way for inexact Double equality testing.

Actually, comparing two float/double values for equality is a bad practice in itself, because floating point numbers suffer from rounding errors. Two numbers which would be equal in symbolic maths may be different to the computer, depending on how they are computed.

The best practice is the second option you used: Math.abs(a - b) < epsilon.
I understand it may be slower than you'd like, but it's the right way to do it. Bitwise comparison may result in two numbers being considered as different even though they're the same, from the point of view of the application (they would be equal if you had computed them by hand, but they are bitwise different due to rounding errors).

mike

java.lang.Double

As shown in the question java.lang.Double.equals() calls public static long doubleToLongBits(double value), which

/**
 * Returns a representation of the specified floating-point value
 * according to the IEEE 754 floating-point "double
 * format" bit layout.

and then checks for equality with ==. (doubleToLongBits internally calls public static native long doubleToRawLongBits(double value), so it is platform dependent).

Here the way the primitive type works.

primitive type double

The floating-point types are float and double, which are conceptually associated with the single-precision 32-bit and double-precision 64-bit format IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).JLS-4.2.3


Operators on floating-point numbers behave as specified by IEEE 754 (with the exception of the remainder operator (§15.17.3)). JLS-4.2.4


So the fastest way would be using primitive types and possibly performing a 'delta check' depending on the needed accuracy. If that's not possible using the methods provided by Double.

One should not use the JUnit assert method, since it performs more checks, one would be better off doing sth like:

boolean eq = Double.valueOf(5.0d).equals(Double.valueOf(2.0d));
Assert.assertTrue(eq);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!