Lo que todo programador debería saber sobre aritmética de punto flotante
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add additional case for handling infinities

+43 -12
+40 -11
content/errors/NearlyEqualsTest.java
··· 4 4 import org.junit.Test; 5 5 6 6 /** 7 - * Test suite to demonstrate a good method for comparing floating-point values using an epsilon. Run via JUnit 4. 8 - * 9 - * Note: this function attempts a "one size fits all" solution. There may be some edge cases for which it still 10 - * produces unexpected results, and some of the tests it was developed to pass probably specify behaviour that is 11 - * not appropriate for some applications. Before using it, make sure it's appropriate for your application! 12 - * 7 + * Test suite to demonstrate a good method for comparing floating-point values 8 + * using an epsilon. Run via JUnit 4. 9 + * 10 + * Note: this function attempts a "one size fits all" solution. There may be 11 + * some edge cases for which it still produces unexpected results, and some of 12 + * the tests it was developed to pass probably specify behaviour that is not 13 + * appropriate for some applications. Before using it, make sure it's 14 + * appropriate for your application! 15 + * 13 16 * From http://floating-point-gui.de 14 - * 17 + * 15 18 * @author Michael Borgwardt 16 19 */ 17 20 public class NearlyEqualsTest { ··· 20 23 final float absB = Math.abs(b); 21 24 final float diff = Math.abs(a - b); 22 25 23 - if (a * b == 0) { // a or b or both are zero 26 + if (a == b) { // shortcut, handles infinities 27 + return true; 28 + } else if (a * b == 0) { // a or b or both are zero 24 29 // relative error is not meaningful here 25 30 return diff < (epsilon * epsilon); 26 31 } else { // use relative error ··· 108 113 assertFalse(nearlyEqual(0.0f, -0.00000001f, 0.00000001f)); 109 114 } 110 115 116 + /** 117 + * Comparisons involving infinities 118 + */ 119 + @Test 120 + public void infinities() { 121 + assertTrue(nearlyEqual(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)); 122 + assertTrue(nearlyEqual(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY)); 123 + assertFalse(nearlyEqual(Float.NEGATIVE_INFINITY, 124 + Float.POSITIVE_INFINITY)); 125 + assertFalse(nearlyEqual(Float.POSITIVE_INFINITY, Float.MAX_VALUE)); 126 + assertFalse(nearlyEqual(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE)); 127 + } 128 + 129 + /** 130 + * Comparisons involving NaN values 131 + */ 132 + @Test 133 + public void nan() { 134 + assertFalse(nearlyEqual(Float.NaN, Float.NaN)); 135 + } 136 + 111 137 /** Comparisons of numbers on opposite sides of 0 */ 112 138 @Test 113 139 public void opposite() { ··· 115 141 assertFalse(nearlyEqual(-1.0f, 1.000000001f)); 116 142 assertFalse(nearlyEqual(-1.000000001f, 1.0f)); 117 143 assertFalse(nearlyEqual(1.0f, -1.000000001f)); 118 - assertTrue(nearlyEqual(1e10f * Float.MIN_VALUE, -1e10f * Float.MIN_VALUE)); 144 + assertTrue(nearlyEqual(1e10f * Float.MIN_VALUE, -1e10f 145 + * Float.MIN_VALUE)); 119 146 } 120 147 121 148 /** ··· 137 164 138 165 assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-12f)); 139 166 assertFalse(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-12f)); 140 - assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, -1e25f * Float.MIN_VALUE, 1e-12f)); 167 + assertFalse(nearlyEqual(1e25f * Float.MIN_VALUE, -1e25f 168 + * Float.MIN_VALUE, 1e-12f)); 141 169 142 170 assertTrue(nearlyEqual(1e25f * Float.MIN_VALUE, 0.0f, 1e-5f)); 143 171 assertTrue(nearlyEqual(0.0f, 1e25f * Float.MIN_VALUE, 1e-5f)); 144 - assertTrue(nearlyEqual(1e20f * Float.MIN_VALUE, -1e20f * Float.MIN_VALUE, 1e-5f)); 172 + assertTrue(nearlyEqual(1e20f * Float.MIN_VALUE, -1e20f 173 + * Float.MIN_VALUE, 1e-5f)); 145 174 } 146 175 147 176 }
+3 -1
content/errors/comparison.html
··· 44 44 final float absB = Math.abs(b); 45 45 final float diff = Math.abs(a - b); 46 46 47 - if (a * b == 0) { // a or b or both are zero 47 + if (a == b) { // shortcut, handles infinities 48 + return true; 49 + } else if (a * b == 0) { // a or b or both are zero 48 50 // relative error is not meaningful here 49 51 return diff < (epsilon * epsilon); 50 52 } else { // use relative error