2016-12-06 6 views
1

무거운 부동 소수점 계산을 수행하는 함수에 대한 테스트를 작성하고 있습니다. 당연히 수레를 계산할 때 완벽하게 정확한 결과를 기대하지는 않습니다. 그러나 이것은 예상 된 결과를 함수에 의해 생성 된 실제 결과와 비교해야하기 때문에 테스트에서 문제가됩니다.감소 된 정밀도를 가진 부동 소수점 목록 비교

내 함수의 결과는 float의 별칭입니다. 예를 들어 :

(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는 하나 개의 테스트가 아닌 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 : BTW

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

참고. 그 Common Lisp은 또한 double floats를 제공합니다 ...