cej38 <junkerme...@gmail.com> writes:

> (defn float=
>   ([x y] (float= x y 0.00001))
>   ([x y epsilon]
>      (let [scale (if (or (zero? x) (zero? y)) 1 (Math/abs x))]
>        (<= (Math/abs (- x y)) (* scale epsilon)))) )

You're scaling epsilon incorrectly here. Epsilon defines the smallest
value that yields a value greater than one when added to one. If you're
not using it along with one, you're using it incorrectly.

What you need to do is scale epsilon by having its exponent match the
value with which you want to use it, while maintaining its mantissa. The
C library offers functions ldexp()¹ and frexp()² to split and scale the
exponent of a floating point number, respectively; Common Lisp offers
DECODE-FLOAT³ and SCALE-FLOAT for the same purpose.

I don't know of any standard functions in Java -- or Clojure -- that
allow one to destructure a floating point number like this. It's
possible to use Float#floatToRawIntBits(), an understanding of IEEE 754,
and tweezers to get there.

If you assume you have a function called `scaled-epsilon' that accepts
the exemplar value with which you intend to use epsilon,

  (defn scaled-epsilon [n] ...)

you can use the following function `same?' to compare your floating
point values, assuming they're nonnegative:

,----
| (defn same?
|   [m n]
|   (if (< n m)
|       (sufficiently-close? n m)
|       (sufficiently-close? m n)))
| 
| (defn- sufficiently-close?
|   [smaller larger]
|   (or (zero? larger)
|       (if (zero? smaller)
|           (< larger (scaled-epsilon 0.0)))
|           (zero? (- 1 (/ smaller larger)))))
`----

Note too that scaling epsilon must take into account whether you intend
to add it or subtract it from some companion number. It's common to use
the word "epsilon" to mean some fudge factor without considering what
the value really means for a floating point number. Indeed, using it
properly in Java is still too difficult. 


Footnotes: 
¹ http://www.dinkumware.com/manuals/?manual=compleat&page=math.html#frexp
² http://www.dinkumware.com/manuals/?manual=compleat&page=math.html#ldexp
³ 
http://www.lispworks.com/documentation/HyperSpec/Body/f_dec_fl.htm#decode-float
  http://www.lispworks.com/documentation/HyperSpec/Body/f_dec_fl.htm#scale-float

-- 
Steven E. Harris

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to