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