Approximate equality: Difference between revisions

Add Common Lisp implementation
(→‎{{header|Haskell}}: added solution)
(Add Common Lisp implementation)
Line 276:
-2.00000000000000044409, -2 => 0
3.141592653589793116, 3.141592653589793116 => 1</pre>
 
=={{header|Common Lisp}}==
This solution compares the normalized (i.e. between 0.5 and 1 on implementations which use binary floating point) significands of the floating point numbers, correcting each significand by half the difference in the exponents so that the corrected numbers used for comparison have the same difference in order of magnitude as the original numbers and are stable when the order of the arguments is changed. Unlike the metric of comparing the difference to some fraction of the numbers' size, this approach only requires a single floating point operation (subtraction), and more directly maps to the fundamental issue which leads to the need for floating-point comparisons, i.e. the limited precision of the significand.
 
<lang lisp>
(defun approx-equal (float1 float2 &optional (threshold 0.000001))
"Determine whether float1 and float2 are equal; THRESHOLD is the
maximum allowable difference between normalized significands of floats
with the same exponent. The significands are scaled appropriately
before comparison for floats with different exponents."
(multiple-value-bind (sig1 exp1 sign1) (decode-float float1)
(multiple-value-bind (sig2 exp2 sign2) (decode-float float2)
(let ((cmp1 (float-sign sign1 (scale-float sig1 (floor (- exp1 exp2) 2))))
(cmp2 (float-sign sign2 (scale-float sig2 (floor (- exp2 exp1) 2)))))
(< (abs (- cmp1 cmp2)) threshold)))))
</lang>
 
=={{header|D}}==
Anonymous user