2

I am trying to learn Clojure and tried defining this simple function:

user=> (defn triple [arg] (* 3 arg))
#'user/triple
user=> (triple 1)
3
user=> (triple 1.01)
3.0300000000000002

Can anyone explain why there is a 2 at the end of the result here?

liwp
  • 6,746
  • 1
  • 27
  • 39
  • You could read some analysis on the problem here: http://stackoverflow.com/questions/9136860/how-to-check-dependencies-of-floats/9136907#9136907 – Gangnus Mar 05 '12 at 20:38
  • Note that this is not a clojure-specific issue, but one of how computers handle arithmetic in general. – Kevin Kostlan Jun 11 '15 at 00:33

2 Answers2

12

Due to the representation of floating point numbers on computers, operations on these numbers are not precise. It applies both to JVM and physical machines. See Floating point inaccuracy examples for a longer discussion. There's also a comprehensive article What Every Computer Scientist Should Know About Floating-Point Arithmetic linked in the answers to that question.

Community
  • 1
  • 1
Jan
  • 11,636
  • 38
  • 47
6

It's due to floating point inaccuracy, which affects all languages with floating point representations. There are some values that cannot be accurately represented with floating point numbers.

Fortunately, Clojure also has support for high precision numerics, so you can do:

(defn triple [arg] (* 3 arg))
(triple 1.01M)
=> 3.03M

Note the use of "M" at the end of numeric constants to indicate that you want to use high precision numbers. In this case java.math.BigDecimal numbers are used by Clojure under the hood.

Community
  • 1
  • 1
mikera
  • 105,238
  • 25
  • 256
  • 415
  • 1
    In fact, when you use the M notation, you get not just high precision but arbitrary precision. It isn't just a matter of jumping from 32 bits to 64 bits. – user100464 Feb 29 '12 at 14:25
  • 1
    Just for completeness, it also works with ratios e.g. (triple (/ 101 100)) =>303/100 – status203 Mar 01 '12 at 10:50