The current implementation of conversion of clojure.lang.Ratio class
to BigDecimal (via bigdec) or to a fixed precision floating point
value is not what one would expect.  For example:

user> (double (/ (expt 2 1024) 3))
Infinity
when in fact it should return: 5.992310449541053E307

and

user=> (bigdec (/ 1 2))
0M
when in fact it should return: 0.5M

These two issues are the symptoms of two different problems, the first
is the current implementation of Ratio.doubleValue which simply
converts the numerator and denominator of the Ratio to a double and
then divides.  The problem with this is that Ratio stores the
numerator and denominator as BigInteger objects, and when either of
these is greater than the size a double can store it will return +/-
Infinity or NaN.  This is easily fixed by having Ratio use BigDecimal
to do the division at a fixed precision of 64-bits.

The second problem is a cause of the definition of the
clojure.core.bignum function which has no cond clause for a ratio.
This can be solved by adding a clause and having Ratio expose a
"decimalValue" function which would perform a BigDecimal division
call.  There is, however, a catch to this method.  If you were to
naively implement this you would have (bigdec (/ 1 3)) throw
ArithmeticException due to a non-terminating decimal expansion, which
would counter to what it currently does, which is always give back a
valid BigInteger object or fail at the cast.  This could be solved by
adding a decimalValueSafe function that would simply catch this and
try again at a fixed precision (say double-double 128-bit).  The other
option would be to force an integer division on these non-terminating
expansions, but I think that would be counter intuitive.

I have uploaded a diff [1] that has the fairly easy changes that would
need to be made to Ratio and bigdec.

[1] 
http://clojure.googlegroups.com/web/ratio-conv.diff?gsc=A8P14BYAAACy2j9kAs1fxLcj8emwRH3H-vghgYgES8zAzJdW7J9-8w

--~--~---------~--~----~------------~-------~--~----~
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
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