0
votes

Currently I'm working with Clojure-on-top-of-the-JVM.

The Java language, which exposes the floating point functionality of the JVM, says that we get (exactly) IEEE-754 32-bit single-precision (Java "float") and 64-bit double precision (Java "double") representations and that the JVM may use an "extended precision" implementation (80 bit for "extended double", aka "long double" in some programming languages) during computation. No word on half-precision or quadruple precision for now.

For Clojure-on-top-of-ECMAScript (i.e. ClojureScript), there is a single underlying number type, which happens to be IEEE-754 64-bit double-precision floating point.

It seems that in the case of Clojure-on-the-JVM, the use of "double" is encouraged in all cases where floating points are expected. There is not even a way to test whether a given thing is a single-precision floating point, as float? (perhaps surprisingly) tests whether the thing is any kind of floating-point value. Incongruently, there is a function to "cast to float", called float.

(defn whatf [x] [(double? x) (float? x) (type x)])

; a literal containing a decimal point is mapped to a 
; "Java double" (boxed)

(whatf 0.1)
;=> [true true java.lang.Double]

; an integer is a "Java long" (boxed), as expected:

(whatf 1)
;=> [false false java.lang.Long]

; you can cast to "float", which corresponds to "Java float".
; and "double?" returns false for that:

(whatf (float 1))
;=> [false true java.lang.Float]

; you can cast to "double":

(whatf (double 1))
;=> [true true java.lang.Double]

; operations on "double" yield "double" as expected:

(whatf (*(double 1) (double 1)))
;=> [true true java.lang.Double]

; operations on "float" force to "double" immediately:

(whatf (*(float 1) (float 1)))
;=> [true true java.lang.Double]

; of course one can always cast, but what's the use of that:

(whatf (float (*(float 1) (float 1))))
[false true java.lang.Float]

So, the programmer is encouraged to not think in terms of precision and let Clojure choose for him/her -- and Clojure chooses IEEE binary64 throughout. Is this the gist of the matter?

1
"Clojure in Action" has a table of the numeric types .. no mention of float, only double (more precisely, "Java double"). So there. Stay with double!David Tonhofer

1 Answers

3
votes

I would say that Clojure/Java makes it straightforward to use only 64-bit Java type double, because of several reasons:

  1. double is the default type you get when you write a floating point literal number, e.g. 1.0
  2. double is the default type returned when doing arithmetic that returns a floating point type
  3. For the loop construct and function parameter and return values that you want to cause Java primitive values to be used, Clojure supports double but not float there.

It is possible to use arrays of float and individual boxed Float values, but you have to work a bit more at it.