Subject: Re: equality of floating point numbers
From: Erik Naggum <erik@naggum.no>
Date: 1997/03/04
Newsgroups: comp.lang.lisp
Message-ID: <3066494244824844@naggum.no>


* Kevin Mayall
| A friend recently gave me a crash-course in the issues of computing the
| equality of floating-point numbers.  I've written functions such as f=,
| f<, f>, etc., which use an epsilon value to test for fp equality.  I want
| to make these into CLOS methods on =, <, >, etc., for arguments of the
| class, Float (that way, I don't have to worry about whether I'm calling
| the fp or non-fp function).  I'm led to believe this is common practice
| in CL.
| 
| So my question is how do CL programmers generally hide these fp functions
| so that they may be used via the regular =, <, >, etc.  functions?

if they do this, they do it by creating a new package that inherits from
the "COMMON-LISP" package and then shadows the relevant functions.  they
also define a methods that do not take objects of type float.

    (defpackage :fuzzy
      (:use :common-lisp)
      (:shadow "=" "<" "<=" ">" ">=" "zerop")
      (:export "=" "<" "<=" ">" ">=" "zerop"))

    (in-package :fuzzy)

    (defconstant epsilon 1e-4)
      (cl:< (- epsilon) x epsilon))
    (defun = (x y)
      (cl:< (- epsilon) (- x y) epsilon))
    (defun < (x y)
      (cl:< (- x y) epsilon))
    (defun <= (x y)
      (cl:<= (- x y) epsilon))
    (defun > (x y)
      (cl:> (- x y) (- epsilon)))
    (defun >= (x y)
      (cl:>= (- x y) (- epsilon)))
    

(of course, you know how to do the fuzzy comparisons better than I do, and
the above might not even be correct implementations, but this should only
illustrate how the package system may be used.)

note that the comparison functions in the COMMON-LISP package all take any
number of arguments.  you may wish to implement this functionality if you
run "normal" code, since it is quite common to test for ranges with, e.g.,
(< low x high).  if you do, note that (OP x y z...) is the same as
(and (OP x y) (OP y z...)) for all OPs _except_ /=.

#\Erik
-- 
if you think big enough, you never have to do it