clojure.test 应该断言两个不同的浮点数在一定范围内相等



我正在使用clojure.test进行单元测试。

某些测试失败是因为非常接近的浮点数被认为是不同的。

expected: (= expected result)
actual: (not (= 1.0 0.9999999999999998))
expected: (= expected result)
actual: (not (= 0.5 0.4999999999999999))

我需要指示 clojure.test 理解(= 0.9999 1.0)是真的。

例如,使用 NUnit,我可以使用 Is.EqualTo((。Within(( 来实现这一点。

注意

在我的具体情况下,1.00.999实际上是一回事。

找到解决这个问题的好解决方案是我多年前开始使用Clojure时遇到的第一个问题之一。 我在 Tupelo 库中创建了rel=函数,正是为此目的:

(rel= val1 val2 & opts)  
"Returns true if 2 double-precision numbers are relatively equal, 
else false. Relative equality is specified as either (1) the N 
most significant digits are equal, or (2) the absolute difference 
is less than a tolerance value.  Input values are coerced to double 
before comparison."

这是在行动:

(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(is   (rel=   123450000   123456789  :digits 4 )) ; .12345 * 10^9
(isnt (rel=   123450000   123456789  :digits 6 ))
(is   (rel= 0.123450000 0.123456789  :digits 4 )) ; .12345 * 1
(isnt (rel= 0.123450000 0.123456789  :digits 6 ))
(is   (rel=  1  1.001  :tol 0.01   )) ; :tol value is absolute error
(isnt (rel=  1  1.001  :tol 0.0001 )))

我在clojure.test的API中没有看到任何东西,也不想要其他依赖项,所以我写了一个close-to函数:

(ns floats-test
(:require [clojure.test :refer :all]))
(defn abs
[x]
(max x (- x)))
(defn close-to
[x y epsilon]
(<= (abs (- x y)) epsilon))
(deftest floats...
(testing "floats are equal"
(is      (close-to 0.000000001 0.00000002  1e-7)))
(testing "floats are equal (other direction)"
(is      (close-to 0.000000002 0.00000001  1e-7)))
(testing "floats aren't equal"
(is (not (close-to 0.000000001 0.000001    1e-7))))
(testing "floats aren't equal (other direction)"
(is (not (close-to 0.000001    0.000000001 1e-7)))))

最新更新