2016-12-06 58 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也提供雙浮點數...