Clojure:减法中的舍入不一致

Clojure:减法中的舍入不一致,clojure,rounding,numerical-stability,Clojure,Rounding,Numerical Stability,我正在编写一段代码,其中数字相等是几个逻辑条件中的一个重要因素。Clojure正在做一件我不太了解的事情来解释。例如: 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

我正在编写一段代码,其中数字相等是几个逻辑条件中的一个重要因素。Clojure正在做一件我不太了解的事情来解释。例如:

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

似乎在某些情况下,Clojure numerics将减法理解为0.1,而在其他情况下则不然。这是怎么回事

默认情况下,这些结果以小数表示,并带有固有的舍入误差。您可以通过在字母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
要对十进制变量执行相同操作,请使用bigdec形式:

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

在所讨论的数字文本中添加一些
M
s可以解决这些症状,但无助于提高David对浮点数学基础知识的理解。请参阅经典,或关于浮点不精确性的众多问题中的任何一个。这里有两个我很容易找到的例子;我已经在Clojure身上看到了至少三个,但是通过搜索很难找到它们


如果这些数字存储在其他地方的变量中,我该怎么做?当这些数字来自其他地方时,可能没有多大用处,但如果你对准确性感兴趣,你也应该知道Clojure的比率:(-5 49/10)=>1/10,但“添加一些Ms”是解决他的问题的唯一办法,或者你能看到其他的解决方案吗?有很多好的解决方案。例如,不要使用像4.5这样的小数,而是使用像9/20这样的有理数,它们具有无限的精度。或者将所有的数乘以10,然后用45这样的整数运算,这样的整数具有足够的精度。或者,不要依赖严格的等式,而是使用“足够好”与ε进行比较。使用bigdecimals并不能完全解决这个问题,因为您根本无法将1/3这样的数字表示为bigdecimal。(当然,我的乘法+整数解决方案也有同样的问题)