From c98cbf3a408048a843aeadf6dba8ebacd12c197d Mon Sep 17 00:00:00 2001 From: Michael Borgwardt Date: Wed, 2 Feb 2011 21:16:36 +0100 Subject: [PATCH] Add additional case for handling infinities --- content/errors/NearlyEqualsTest.java | 51 ++++++++++++++++++++++------ content/errors/comparison.html | 4 ++- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/content/errors/NearlyEqualsTest.java b/content/errors/NearlyEqualsTest.java index abf9b03..30aa32b 100644 --- a/content/errors/NearlyEqualsTest.java +++ b/content/errors/NearlyEqualsTest.java @@ -4,14 +4,17 @@ import org.junit.Test; /** - * Test suite to demonstrate a good method for comparing floating-point values using an epsilon. Run via JUnit 4. - * - * Note: this function attempts a "one size fits all" solution. There may be some edge cases for which it still - * produces unexpected results, and some of the tests it 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! - * + * Test suite to demonstrate a good method for comparing floating-point values + * using an epsilon. Run via JUnit 4. + * + * Note: this function attempts a "one size fits all" solution. There may be + * some edge cases for which it still produces unexpected results, and some of + * the tests it 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! + * * From http://floating-point-gui.de - * + * * @author Michael Borgwardt */ public class NearlyEqualsTest { @@ -20,7 +23,9 @@ public static boolean nearlyEqual(float a, float b, float epsilon) { final float absB = Math.abs(b); final float diff = Math.abs(a - b); - if (a * b == 0) { // a or b or both are zero + if (a == b) { // shortcut, handles infinities + return true; + } else if (a * b == 0) { // a or b or both are zero // relative error is not meaningful here return diff < (epsilon * epsilon); } else { // use relative error @@ -108,6 +113,27 @@ public void zero() { assertFalse(nearlyEqual(0.0f, -0.00000001f, 0.00000001f)); } + /** + * Comparisons involving infinities + */ + @Test + public void infinities() { + assertTrue(nearlyEqual(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)); + assertTrue(nearlyEqual(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY)); + assertFalse(nearlyEqual(Float.NEGATIVE_INFINITY, + Float.POSITIVE_INFINITY)); + assertFalse(nearlyEqual(Float.POSITIVE_INFINITY, Float.MAX_VALUE)); + assertFalse(nearlyEqual(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE)); + } + + /** + * Comparisons involving NaN values + */ + @Test + public void nan() { + assertFalse(nearlyEqual(Float.NaN, Float.NaN)); + } + /** Comparisons of numbers on opposite sides of 0 */ @Test public void opposite() { @@ -115,7 +141,8 @@ public void opposite() { assertFalse(nearlyEqual(-1.0f, 1.000000001f)); assertFalse(nearlyEqual(-1.000000001f, 1.0f)); assertFalse(nearlyEqual(1.0f, -1.000000001f)); - assertTrue(nearlyEqual(1e10f * Float.MIN_VALUE, -1e10f * Float.MIN_VALUE)); + assertTrue(nearlyEqual(1e10f * Float.MIN_VALUE, -1e10f + * Float.MIN_VALUE)); } /** @@ -137,11 +164,13 @@ public void ulp() { assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-12f)); assertFalse(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-12f)); - assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, -1e25f * Float.MIN_VALUE, 1e-12f)); + assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, -1e25f + * Float.MIN_VALUE, 1e-12f)); assertTrue(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-5f)); assertTrue(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-5f)); - assertTrue(nearlyEqual(1e20f * Float.MIN_VALUE, -1e20f * Float.MIN_VALUE, 1e-5f)); + assertTrue(nearlyEqual(1e20f * Float.MIN_VALUE, -1e20f + * Float.MIN_VALUE, 1e-5f)); } } diff --git a/content/errors/comparison.html b/content/errors/comparison.html index e47e962..bbf19b2 100644 --- a/content/errors/comparison.html +++ b/content/errors/comparison.html @@ -44,7 +44,9 @@ final float absB = Math.abs(b); final float diff = Math.abs(a - b); - if (a * b == 0) { // a or b or both are zero + if (a == b) { // shortcut, handles infinities + return true; + } else if (a * b == 0) { // a or b or both are zero // relative error is not meaningful here return diff < (epsilon * epsilon); } else { // use relative error