clojure numbers, ops combinations

15 views
Skip to first unread message

Mike Hinchey

unread,
Aug 5, 2009, 3:01:20 AM8/5/09
to cloju...@googlegroups.com
I think I've found some edge case problems with numbers in clojure.  If you agree, and give me some direction, I can work on the fix.

user> (class (bit-shift-left 1 100001))
java.math.BigInteger
user> (.equals Double/POSITIVE_INFINITY (bit-shift-left 1 100001))
false
user> (= Double/POSITIVE_INFINITY (bit-shift-left 1 100001))
true

This happens because Numbers.DoubleOps.equiv() uses the .doubleValue of y.  (I suppose java .equals is false here only because they are different classes, so that's not worth much.)  I'm not sure the best way to fix this.  Is it correct for DoubleOps.opsWith(BigIntegerOps) to return DoubleOps?  BigIntegerOps.opsWith(DoubleOps) does the same.  It seems this could lead to overflow in a few cases (see below).  If these opsWith methods returned BigDecimalOps, that might be best.  Although toBigDecimal(infinity) will throw an exception, but that might be a good thing.

user> (.equals Double/POSITIVE_INFINITY Double/POSITIVE_INFINITY)
true
user> (= Double/POSITIVE_INFINITY Double/POSITIVE_INFINITY)
true

Infinity isn't a real number, so this result from java seems like bad policy to me.  Regardless of java, shouldn't clojure's = return false?  I think the math predicates (=, pos?, neg?, zero?) should return something for infinity, but the ops should throw exceptions.  This would be a bigger change since both ops and preds use the same classes in Numbers.

user> (loop [d 1.0,
             p nil]
        ;(when (= 0 (mod d 100000000)) (println d))
        (if (= d p)
          d
          (recur (* 10000.0 d) d)))
Infinity
user> (loop [d 1.0
             p nil]
        ;(when (= 0 (mod d 100000000)) (println d))
        (if (or (= d p) (> d Double/MAX_VALUE))
          d
          (recur (* 10000.0M d) d)))
Infinity

The only way this works as I want is if both literals (also 1.0) have the M.  Would it be preferable to have Double and BigDecimal combine as a BigDecimal rather than the lesser Double?

(I'm using the master branch of clojure.)

-Mike

Jonathan Smith

unread,
Aug 5, 2009, 9:32:45 AM8/5/09
to Clojure Dev
I may be off base here, but...

= Isn't the math predicate, it is comparing a bunch of things (I think
object equality... it is at very least polymorphic..)

== is the math predicate. (it may be that = just gloms directly onto
== for numbers, but i don't know/remember)

Did you try this out with == (?) I would but I don't have a clojure
repl here.

-Jon

Mike Hinchey

unread,
Aug 5, 2009, 11:13:05 AM8/5/09
to cloju...@googlegroups.com
== calls Numbers/equiv.  = calls Util/equiv, which then calls Numbers/equiv. So it's the same thing, just faster.

-Mike
Reply all
Reply to author
Forward
0 new messages