Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

OpenSCAD User Manual/General/Nearly Equal

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Example code for using MIN_NORMAL and MAX.VALUE to correctly evaluate the difference between two floating point values that have a very small difference, or are themselves very small. Two FP values that should have the same value but are calculated in different ways may have small differences in their encodings when their differences are close to, or less than, the Min.Normal value derived from the numerical representation. The epsilon value may be set to a value of difference acceptable to the application using nearlyEqual() when accuracy is relaxed from the theoretical best values of MIN_NORMAL and MAX.VALUE public static boolean nearlyEqual(float a, float b, float epsilon) { final float absA = Math.abs(a); final float absB = Math.abs(b); final float diff = Math.abs(a - b); if (a == b) { // shortcut, handles infinities return true; } else if (a == 0 || b == 0 || (absA + absB < Float.MIN_NORMAL)) { // a or b is zero or both are extremely close to it // relative error is less meaningful here return diff < (epsilon * Float.MIN_NORMAL); } else { // use relative error return diff / Math.min((absA + absB), Float.MAX_VALUE) < epsilon; } } The following SCAD function returns true when two floating point values are within epsilon's value of each other. This form of comparison takes account of the limitations of representing floating point values as binary encoded values. The Min_Normal value is derived from the 64 bit values used in OpenSCAD. function nearly_equal( a, b, epsilon=0.00001 ) = let(absA = abs(a), absB = abs(b), diff = abs(a - b) ) a == b ? true // shortcut, handles infinities : a == 0 || b == 0 || (absA + absB < Min_Normal ) ? // when a or b are zero or both are extremely close to it // relative error is less meaningful here diff < (epsilon * Min_Normal) : diff / min((absA + absB), MAX_VALUE) < epsilon ; echo( "testing _nearly_equal()" ); echo( _neq = _nearly_equal( 0.01000000000001, 0.01000000000001) ); echo( _neq = _nearly_equal( 0.01000000000009, 0.01000000000001) ); echo( _neq1= _nearly_equal( 0.010001, 0.010001) ); echo( _neq3= _nearly_equal( 0.010003, 0.010001) ); echo( _neq9= _nearly_equal( 0.010009, 0.010001) ); echo( "testing nearly_equal()" ); echo( neq= nearly_equal( 0.01000001, 0.01000001 ) ); echo( neq= nearly_equal( 0.0100001, 0.01000001 ) ); echo( neq= nearly_equal( 0.010001, 0.01000001 ) ); assert( _nearly_equal( 0.01000000000000001, 0.01000000000000001) ); assert( _nearly_equal( 0.010001, 0.010001) ); assert( ! _nearly_equal( 0.010003, 0.010001) ); assert( ! _nearly_equal( 0.010009, 0.010001) ); assert( nearly_equal( 0.01000000000000001, 0.01000000000000001) ); assert( nearly_equal( 0.0100001, 0.01000001 ) ); assert( ! nearly_equal( 0.010001, 0.01000001 ) );