2016-12-06 100 views
1

我正在为一个执行繁重浮点数字计算的函数编写测试。自然计算浮动时,你不期望得到完美的结果。然而,这对我的测试来说是一个问题,因为我需要将预期结果与函数产生的实际结果进行比较。比较精度下降的浮点数列表

我的功能的结果是一个花车的alist。例如:

(is (my-function "arg1" "arg2") 
    '((0 1.0) 
     (1 2.0))) 

会产生:

((0 1.00000014) (1 2.1)) is expected to be ((0 1) (1 2.1)) 

我的问题是:我如何可以遍历ALIST和精度下降比较各是多少?

prove允许我在比较预期结果和实际结果时指定测试函数。这里是我的代码到目前为止:

(defun compare-floats (f1 f2) 
    (= (round-to f1 6) 
    (round-to f2 6))) 

(defun round-to (number &optional (precision 6)) 
    (let ((div (expt 10 precision))) 
    (/ (round (* number div)) div))) 

(is (my-function "arg1" "arg2") 
    '((0 1.0) 
     (1 2.0)) 
    :test #'(lambda (expected actual) 
       (every #'identity 
         (mapcar #'(lambda (list1 list2) 
            (compare-floats (second list1) 
                (second list2))) 
           expected 
           actual)))) 

这工作,但它不是很优雅。

回答

2

在我看来是:

(every #'identity 
     (mapcar #'(lambda (list1 list2) 
        (compare-floats (second list1) 
            (second list2))) 
       expected 
       actual)) 

...可以写成:

(every (lambda (list1 list2) 
     (compare-floats (second list1) (second list2))) 
     actual 
     expected) 

注意every将停止作为一个测试返回nil,这是不尽快比较数字在你的原始功能的情况下。如果你执行了重要的副作用,这将是不同的。

至于测试的花车,我会用这样的事情:

(defun floats-rougly-equal-p (f1 f2 &optional (precision 1e-6)) 
    (< (abs (- f1 f2)) precision)) 

但是,如果你的代码的工作,不要试图花太多时间寻找最优雅的方法。

+0

谢谢!确实更好。 :)我是“花时间”,因为我试图在编程上变得更好:)当然可以说一个好的开发人员知道什么时候该继续前进...... – tsikov

+1

@tsikov我明白了。这只是一个警告:'(宣布(优化(优雅3)))'不是标准化的。 – coredump

2

LOOP

(loop for (nil a) in actual 
     and (nil b) in expected 
     always (compare-floats a b)) 

注BTW。 Common Lisp也提供双浮点数...