LISP中浮点的神秘问题 - 时间轴生成 [英] Mysterious problem with floating point in LISP - time axis generation

查看:170
本文介绍了LISP中浮点的神秘问题 - 时间轴生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我知道什么和如何工作浮点。但是,当我处理它的时候,它不会停下来困扰我。



我尝试做一些时间轴生成函数。这个想法很简单。为了让smt像这样

 (defun make-time-axis(start step stop)
...)
$ / code>

所以,当你用例如

(make-time-axis 0 0.1 1.2)

result将是 $ b

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

但是每当我做什么的时候

 从0.1以下的1.2降低0.1收集i)


$ b $ (<最后一站)(cons last(make-time-axis(+ last)) (defun make-time-步)停步)))
(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)

能不能给我一些线索如何得到我想要的?

解决方案

如果你知道浮点数是如何工作的(你已经阅读了每个计算机科学家应该知道什么关于浮点算术,对吗?),你应该认识到你得到了你所要求的。

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



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



由于您使用的是Lisp,所以很容易保留精确形式的数字(例如理性的1/10,而不是浮动0.1),并在最后一分钟转换他们。

pre $ / 10 by 1/10 collect(float i))
(mapcar#'float(make-time-axis 0 1/10 12/10))


Ok, I do know what and how works floating point. But, It doesn't stop to puzzle me whenever I deal with it.

I try to do some time axis generation function. The idea is simple. To make smt like this

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

So, when you call it with e.g.

(make-time-axis 0 0.1 1.2)

result will be

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

But whenever I do whatever

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

or

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

etc.

I getting these results

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

Can anybode give me some clue how to get What I want?

解决方案

If you know how floating point works (you have read What Every Computer Scientist Should Know About Floating Point Arithmetic, right?), you should realize that you got exactly what you asked for.

Mathematical numbers (be they integers, rationals, reals, complex, whatever) have many useful properties. For example, x/10 + y/10 = (x+y)/10. These properties don't hold for floating point numbers.

Given your numerical results, it seems that in your implementation, the value of the floating-point number 0.1 is slightly above the value of the mathematical number 0.1 (which isn't exactly representable as floating point). When you add it up several times, the error eventually rises above the printing precision.

Since you're using Lisp, it's easy to retain numbers in exact form (e.g. the rational 1/10 instead of the float 0.1) and convert them at the last minute.

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

这篇关于LISP中浮点的神秘问题 - 时间轴生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆