Question

I am working on a piece of code where numerical equality is an important factor in several logical conditional. Clojure is doing something I dont know enough about to explain. For example:

user=> (- 5 4.9)
0.09999999999999964
user=> (- 5 4.8)
0.20000000000000018
user=> (- 5 2.9)
2.1
user=> (- 5 2.7)
2.3
user=> (- 5 2.8)
2.2
user=> (- 9 6.9)
2.0999999999999996 
user=> (- 9 2.9)
6.1

It seems like in some circumstance, Clojure numerics understands subtraction to 0.1, in other cases not. What is going on here?

Was it helpful?

Solution

By default these results are expressed as decimals, with the inherent rounding errors. You can switch to using BigDecimals by suffixing with the letter M:

user=> (- 5M 4.9M)
0.1M
user=> (- 5M 4.8M)
0.2M
user=> (- 9M 6.9M)
2.1M
user=> (- 9M 2.9M)
6.1M

To do the same with a variable that's a decimal, use the bigdec form:

user=> (def k 4.9)
#'user/k
user=> (- 5M k)
0.09999999999999964
user=> (- 5M (bigdec k))
0.1M

OTHER TIPS

Adding some Ms to the number literals in question addresses the symptoms, but does nothing to improve David's understanding of the fundamentals of floating-point math. See the classic What Every Computer Scientist Should Know About Floating-Point Arithmetic, or any one of the numerous questions on SO about floating-point inexactness. Here are two examples I could easily find; I've seen at least three for Clojure alone, but it's hard to find them with a search.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top