LISP中浮点的神秘问题 - 时间轴生成

时间:2011-06-03 09:20:55

标签: lisp floating-point

好的,我知道什么以及如何工作浮点数。但是,每当我处理它时,它都不会让我感到困惑。

我尝试做一些时间轴生成功能。这个想法很简单。要像这样做smt

(defun make-time-axis (start step stop)
  ...)

所以,当你用例如。

打电话时
(make-time-axis 0 0.1 1.2)

结果将是

0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 

但每当我做任何事情

(loop for i from 0.0 below 1.2 by 0.1 collect i)

(defun make-time-axis (last step stop)
  (cond  ((< last stop ) (cons last (make-time-axis (+ last step) step stop )))
     (t nil)))

我得到了这些结果

(0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.70000005 0.8000001 0.9000001 1.0000001 1.1000001)

anybode可以给我一些线索如何得到我想要的东西吗?

1 个答案:

答案 0 :(得分:12)

如果你知道浮点是如何工作的(你读过What Every Computer Scientist Should Know About Floating Point Arithmetic,对吧?),你应该意识到你得到了你所要求的。

数学数字(无论是整数,有理数,实数,复数,等等)都有许多有用的属性。例如,x / 10 + y / 10 =(x + y)/ 10。这些属性不适用于浮点数。

鉴于您的数值结果,似乎在您的实现中,浮点数0.1的值略高于数学数字0.1的值(这不能完全表示为浮点数)。当您多次添加时,错误最终会超出打印精度。

由于您使用的是Lisp,因此很容易以精确的形式保留数字(例如,合理的1/10而不是浮点数0.1)并在最后一刻转换它们。

(loop for i from 0 below 12/10 by 1/10 collect (float i))
(mapcar #'float (make-time-axis 0 1/10 12/10))