比较精度降低的浮点数列表

Compare lists of floats with decreased precision

我正在为执行大量浮点数计算的函数编写测试。当然,在计算浮点数时,您不会期望获得完全准确的结果。然而,这对我的测试来说是个问题,因为我需要将预期结果与函数产生的实际结果进行比较。

我的函数的结果是一个浮点数列表。例如:

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

这可行,但不是很优雅。

在我看来:

(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 将在一次测试 returns NIL 后立即停止比较数字,这在您的原始函数中不是这种情况。如果您执行了重要的副作用,这将有所不同。

至于测试浮动,我会使用这样的东西:

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

但如果您的代码有效,请不要花太多时间寻找最优雅的方法。

循环:

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

顺便说一句。 Common Lisp 还提供双浮点数...