Why does Clojure have it's own naive implementation of max for doubles instead of using max from java.lang.Math which has necessary checks for NaN and the positive and negative zeros?
On Sun, 30 Oct 2011 15:36:23 +0100 Ben Smith-Mannschott <bsmith.o...@gmail.com> wrote: > On Sun, Oct 30, 2011 at 10:02, bOR_ <boris.sch...@gmail.com> wrote: > > Hi all, > > Ran into something unexpected with "max". > > user> (sd-age-female 13) > > > > > > [10 NaN 0.746555245613119] > > > > > > user> (apply max (sd-age-female 13)) > > > > 0.746555245613119 > > TL;DR: Don't expect sensible answers when NaN is involved. > > The implementation of max in Clojure core assumes that it's possible > to compare the things it is given and get consistent results. > > clojure.core: > # > # (defn max > # "Returns the greatest of the nums." > # {:added "1.0" > # :inline-arities >1? > # :inline (nary-inline 'max)} > # ([x] x) > # ([x y] (. clojure.lang.Numbers (max x y))) > # ([x y & more] > # (reduce1 max (max x y) more))) > > clojure.lang.Numbers: > # > # static public double max(double x, double y){ > # if(x > y){ > # return x; > # } else { > # return y; > # } > # } > > This doesn't turn out to be the case with IEEE floating point numbers > because of the behavior of NaN, as mandated by the standard. > > For every number that is not NaN, the world works as we expect: > > a < b && b < c implies a < c > a < b implies !(a >= b) > a < b implies b > a > a == b implies b == a > > But, adding NaN to the mix changes all that. NaN is like a great big > black hole for truth. All of these are false: > > (NaN == NaN) > (NaN < b) > (NaN >= b) > ... > > http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.4 > # > # An operation that overflows produces a signed infinity, an operation > # that underflows produces a denormalized value or a signed zero, and an > # operation that has no mathematically definite result produces NaN. All > # numeric operations with NaN as an operand produce NaN as a result. As > # has already been described, NaN is unordered, so a numeric comparison > # operation involving one or two NaNs returns false and any != > # comparison involving NaN returns true, including x!=x when x is NaN. > > So, in your example (max [10 NaN 0.74]) what happens is this: > > - (max 10 NaN) discovers that (10 > NaN) -> false, therefore > NaN is chosen as the "max" of the first two is NaN. > > - (max NaN 0.74) discovers that (NaN > 0.74) -> false, therefore > 0.74 is the maximum. > > // Ben > -- Mikhail -- 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