···44import org.junit.Test;
5566/**
77- * Test suite to demonstrate a good method for comparing
88- * floating-point values using an epsilon. Run via JUnit 4.
77+ * Test suite to demonstrate a good method for comparing floating-point values using an epsilon. Run via JUnit 4.
98 *
1010- * Note: this function attempts a "one size fits all" solution. There
1111- * may be some edge cases for which it still produces unexpected results,
1212- * and some of the tests it was developed to pass probably specify behaviour
1313- * that is not appropriate for some applications. Before using it, make
1414- * sure it's appropriate for your application!
99+ * Note: this function attempts a "one size fits all" solution. There may be some edge cases for which it still
1010+ * produces unexpected results, and some of the tests it was developed to pass probably specify behaviour that is
1111+ * not appropriate for some applications. Before using it, make sure it's appropriate for your application!
1512 *
1613 * From http://floating-point-gui.de
1714 *
1815 * @author Michael Borgwardt
1916 */
2020-public class NearlyEqualsTest
2121-{
2222- public static boolean nearlyEqual(float a, float b, float epsilon)
2323- {
1717+public class NearlyEqualsTest {
1818+ public static boolean nearlyEqual(float a, float b, float epsilon) {
2419 final float absA = Math.abs(a);
2520 final float absB = Math.abs(b);
2626- final float diff = Math.abs(a-b);
2121+ final float diff = Math.abs(a - b);
27222828- if (a*b==0) { // a or b or both are zero
2323+ if (a * b == 0) { // a or b or both are zero
2924 // relative error is not meaningful here
3030- return diff < Float.MIN_VALUE / epsilon;
2525+ return diff < (epsilon * epsilon);
3126 } else { // use relative error
3232- return diff / (absA+absB) < epsilon;
2727+ return diff / (absA + absB) < epsilon;
3328 }
3429 }
35303636- public static boolean nearlyEqual(float a, float b)
3737- {
3131+ public static boolean nearlyEqual(float a, float b) {
3832 return nearlyEqual(a, b, 0.000001f);
3933 }
40344135 /** Regular large numbers - generally not problematic */
4242- @Test public void big()
4343- {
3636+ @Test
3737+ public void big() {
4438 assertTrue(nearlyEqual(1000000f, 1000001f));
4539 assertTrue(nearlyEqual(1000001f, 1000000f));
4640 assertFalse(nearlyEqual(10000f, 10001f));
···4842 }
49435044 /** Negative large numbers */
5151- @Test public void bigNeg()
5252- {
4545+ @Test
4646+ public void bigNeg() {
5347 assertTrue(nearlyEqual(-1000000f, -1000001f));
5448 assertTrue(nearlyEqual(-1000001f, -1000000f));
5549 assertFalse(nearlyEqual(-10000f, -10001f));
···5751 }
58525953 /** Numbers around 1 */
6060- @Test public void mid()
6161- {
5454+ @Test
5555+ public void mid() {
6256 assertTrue(nearlyEqual(1.0000001f, 1.0000002f));
6357 assertTrue(nearlyEqual(1.0000002f, 1.0000001f));
6458 assertFalse(nearlyEqual(1.0002f, 1.0001f));
···6660 }
67616862 /** Numbers around -1 */
6969- @Test public void midNeg()
7070- {
6363+ @Test
6464+ public void midNeg() {
7165 assertTrue(nearlyEqual(-1.000001f, -1.000002f));
7266 assertTrue(nearlyEqual(-1.000002f, -1.000001f));
7367 assertFalse(nearlyEqual(-1.0001f, -1.0002f));
···7569 }
76707771 /** Numbers between 1 and 0 */
7878- @Test public void small()
7979- {
7272+ @Test
7373+ public void small() {
8074 assertTrue(nearlyEqual(0.000000001000001f, 0.000000001000002f));
8175 assertTrue(nearlyEqual(0.000000001000002f, 0.000000001000001f));
8276 assertFalse(nearlyEqual(0.000000000001002f, 0.000000000001001f));
···8478 }
85798680 /** Numbers between -1 and 0 */
8787- @Test public void smallNeg()
8888- {
8181+ @Test
8282+ public void smallNeg() {
8983 assertTrue(nearlyEqual(-0.000000001000001f, -0.000000001000002f));
9084 assertTrue(nearlyEqual(-0.000000001000002f, -0.000000001000001f));
9185 assertFalse(nearlyEqual(-0.000000000001002f, -0.000000000001001f));
···9387 }
94889589 /** Comparisons involving zero */
9696- @Test public void zero()
9797- {
9090+ @Test
9191+ public void zero() {
9892 assertTrue(nearlyEqual(0.0f, 0.0f));
9393+ assertTrue(nearlyEqual(0.0f, -0.0f));
9494+ assertTrue(nearlyEqual(-0.0f, -0.0f));
9995 assertFalse(nearlyEqual(0.00000001f, 0.0f));
10096 assertFalse(nearlyEqual(0.0f, 0.00000001f));
9797+ assertFalse(nearlyEqual(-0.00000001f, 0.0f));
9898+ assertFalse(nearlyEqual(0.0f, -0.00000001f));
9999+100100+ assertTrue(nearlyEqual(0.0f, 0.00000001f, 0.01f));
101101+ assertTrue(nearlyEqual(0.00000001f, 0.0f, 0.01f));
102102+ assertFalse(nearlyEqual(0.00000001f, 0.0f, 0.000001f));
103103+ assertFalse(nearlyEqual(0.0f, 0.00000001f, 0.000001f));
104104+105105+ assertTrue(nearlyEqual(0.0f, -0.00000001f, 0.1f));
106106+ assertTrue(nearlyEqual(-0.00000001f, 0.0f, 0.1f));
107107+ assertFalse(nearlyEqual(-0.00000001f, 0.0f, 0.00000001f));
108108+ assertFalse(nearlyEqual(0.0f, -0.00000001f, 0.00000001f));
101109 }
102110103111 /** Comparisons of numbers on opposite sides of 0 */
104104- @Test public void opposite()
105105- {
112112+ @Test
113113+ public void opposite() {
106114 assertFalse(nearlyEqual(1.000000001f, -1.0f));
107115 assertFalse(nearlyEqual(-1.0f, 1.000000001f));
108116 assertFalse(nearlyEqual(-1.000000001f, 1.0f));
109117 assertFalse(nearlyEqual(1.0f, -1.000000001f));
110110- assertTrue(nearlyEqual(10000f*Float.MIN_VALUE, -10000f*Float.MIN_VALUE));
118118+ assertTrue(nearlyEqual(1e10f * Float.MIN_VALUE, -1e10f * Float.MIN_VALUE));
111119 }
112120113121 /**
114114- * The really tricky part - comparisons of numbers
115115- * very close to zero.
122122+ * The really tricky part - comparisons of numbers very close to zero.
116123 */
117117- @Test public void ulp()
118118- {
124124+ @Test
125125+ public void ulp() {
119126 assertTrue(nearlyEqual(Float.MIN_VALUE, -Float.MIN_VALUE));
120127 assertTrue(nearlyEqual(-Float.MIN_VALUE, Float.MIN_VALUE));
121128 assertTrue(nearlyEqual(Float.MIN_VALUE, 0));
···128135 assertFalse(nearlyEqual(Float.MIN_VALUE, 0.000000001f));
129136 assertFalse(nearlyEqual(-Float.MIN_VALUE, 0.000000001f));
130137131131- assertFalse(nearlyEqual(1e20f*Float.MIN_VALUE, 0.0f));
132132- assertFalse(nearlyEqual(0.0f, 1e20f*Float.MIN_VALUE));
133133- assertFalse(nearlyEqual(1e20f*Float.MIN_VALUE, -1e20f*Float.MIN_VALUE));
138138+ assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-12f));
139139+ assertFalse(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-12f));
140140+ assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, -1e25f * Float.MIN_VALUE, 1e-12f));
141141+142142+ assertTrue(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-5f));
143143+ assertTrue(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-5f));
144144+ assertTrue(nearlyEqual(1e20f * Float.MIN_VALUE, -1e20f * Float.MIN_VALUE, 1e-5f));
134145 }
135146136147}
+7-7
content/errors/comparison.html
···40404141 public static boolean nearlyEqual(float a, float b, float epsilon)
4242 {
4343- float absA = Math.abs(a);
4444- float absB = Math.abs(b);
4545- float diff = Math.abs(a-b);
4343+ final float absA = Math.abs(a);
4444+ final float absB = Math.abs(b);
4545+ final float diff = Math.abs(a - b);
46464747- if (a*b==0) { // a or b or both are zero
4747+ if (a * b == 0) { // a or b or both are zero
4848 // relative error is not meaningful here
4949- return diff < Float.MIN_VALUE / epsilon;
4949+ return diff < (epsilon * epsilon);
5050 } else { // use relative error
5151- return diff / (absA+absB) < epsilon;
5151+ return diff / (absA + absB) < epsilon;
5252 }
5353 }
5454···5656uses some quite non-obvious logic. In particular, it has to use a completely different definition of error margin
5757when `a` or `b` is zero, because the classical definition of relative error becomes meaningless in those cases.
58585959-There probably are some cases where the method above still produces unexpected results, and some of the tests
5959+There are some cases where the method above still produces unexpected results (in particular, it's much stricter when one value is nearly zero than when it is exactly zero), and some of the tests
6060it was developed to pass probably specify behaviour that is not appropriate for some applications. Before using it, make sure it's appropriate for your application!
61616262Comparing floating-point values as integers