Similarly to my previous post about Integer numbers, Clojure has a support for floating point numbers, by default mapped as java.lang.Double and arbitrary precise decimals mapped as java.math.BigDecimal.
;; floating point mapped as java.lang.Double
1.0
-3.5
1234e-3
(type 1.0)
;= java.lang.Double
;; BigDecimals
1.0M
-3.5M
29085673904875.0398475293847523984752837465283476583475M
(type 1.0M)
;= java.math.BigDecimal
One difference between integers and floating point decimals in Clojure is in the way it handles basic computation. We seen in the previous post that when try to mix “small” integers and “big” integers in a calculation, Clojure always uses the largest type as return type. This seems not to be happening for the floating point and big decimals
(type (+ 1 1N))
;= clojure.lang.BigInt
(type (+ 1.0 1.0M))
;= java.lang.Double
It is really important to keep in mind this subtle difference because you need only one Double mixed in your “precise” calculus to truncate the precision down to a java.lang.Double with potentially disastrous effects.
(+ 0.3M 0.3M 0.3M 0.1M )
;= 1.0M
(type (+ 0.3M 0.3M 0.3M 0.1M ))
;= java.math.BigDecimal
;; /---- Missing 'M'
(+ 0.3M 0.3M 0.3 0.1M )
;= 0.9999999999999999
(type (+ 0.3M 0.3M 0.3 0.1M ))
;= java.lang.Double
Next we’ll see Clojure rationals in action.