7

In Scheme I can do:

#;> (numerator 1/3)
1
#;> (denominator 1/3)
3

In Clojure I can do something similar:

user=> (numerator 1/3)
1
user=> (denominator 1/3)
3

But in Scheme I can do:

#;> (numerator 0.3)
3.0

and it is not possible in Clojure:

user=> (numerator 0.3)

ClassCastException java.lang.Double cannot be cast to clojure.lang.Ratio  clojure.core/numerator (core.clj:3306)

How can I convert a Double (or actually any kind of number) into a clojure.lang.Ratio?

In Scheme we have also inexact->exact what would be something like "double to ratio" in Clojure, but I can't find anything similar to it.

Felipe
  • 16,649
  • 11
  • 68
  • 92

1 Answers1

12

Ooh, I know this one!

user=> (rationalize 0.3)
3/10
user=> (numerator (rationalize 0.3))
3

But the OP points out that this doesn't work for all numbers:

user=> (numerator (rationalize 1))
ClassCastException java.lang.Long cannot be cast to clojure.lang.Ratio  clojure.core/numerator (core.clj:3306)

see his Java interop workaround in his answer.


[edit] OP here:

Here is a more generic solution:

user=> (numerator (clojure.lang.Numbers/toRatio (rationalize 1)))
1
user=> (numerator (clojure.lang.Numbers/toRatio (rationalize 0.3)))
3
user=> (numerator (clojure.lang.Numbers/toRatio (rationalize 1/3)))
1
Felipe
  • 16,649
  • 11
  • 68
  • 92
YosemiteMark
  • 675
  • 1
  • 6
  • 13
  • Unfortunately does not work for every number, see: user=> (numerator (rationalize 1)) ClassCastException java.lang.Long cannot be cast to clojure.lang.Ratio clojure.core/numerator (core.clj:3306) – Felipe Aug 08 '14 at 01:50
  • You are right. That seems unfortunate - I wonder if it is intended that (rationalize 1) returns a Long? – YosemiteMark Aug 08 '14 at 02:00
  • It seems to be a performance hit, but it is a weird behavior. – Felipe Aug 08 '14 at 02:02
  • 4
    `(rational? 3)` returns `true`, but `(numerator 3)` blows up. Can't be right. – Thumbnail Aug 08 '14 at 11:08
  • 2
    Where is @Rich Hickey? :) – Felipe Aug 22 '14 at 20:28
  • 1
    Looks like a bug and I've found no evidence of it already being reported. IMO the `numerator` should be fixed, since integers are also rational numbers by definition of the latter. "Type-safe-me", however, tells me that `rationalize` should always return an instance of `Ratio`. Huh. – D-side Jul 16 '15 at 10:59