2016-12-06 17 views
1

重い浮動小数点数の計算を行う関数のテストを書いています。浮動体を計算するときは、当然、完全に正確な結果を得ることは期待できません。しかし、これは私のテストでは、期待される結果と実際の結果とを比較する必要があるため、問題です。精度が低下した浮動小数点数のリストを比較する

私の関数の結果は、浮動小数点数のリストです。たとえば:

(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)) 

を私の質問は:は、どのように私は連想リストを横断し、減少した精度で各数値を比較することができますか?

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は一つのテストではありませんNILを返すとすぐに数字を比較停止します

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

に留意されたいです。大文字と小文字を区別します。重要な副作用を実行した場合、これは異なる場合があります。

テスト山車のためとして、私はこのようなものを使用しているでしょう:

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

をしかし、あなたのコードが動作する場合、最もエレガントなアプローチを見つけ、あまりにも多くの時間を過ごすためにしようとしないでください。

+0

ありがとう!確かに多くのより良い。 :)私はプログラミングでより良くなるように努力しているので、私は「時間を費やしています」。もちろん、良い開発者はいつ移動するかを知っていると言うことができます。 – tsikov

+1

@tsikov私は理解しています。それはちょうど警告だった: '(declare(optimize(elegance 3)))'は標準化されていない。 – coredump

2

LOOP:ところで

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

注意。そのCommon Lispは二重浮動小数点も提供します...

関連する問題