Lisp 理解函数中的数字数据类型

Lisp 理解函数中的数字数据类型,lisp,common-lisp,clisp,Lisp,Common Lisp,Clisp,这是我之前发布的一篇文章的后续文章。很抱歉,这可能是一个基本的Lisp概念,但我还没有掌握它 对于这个问题,我使用的是gnuclisp2.49(2010-07-07) 假设我有以下函数,它通过牛顿法简单地确定平方根: (defun sr (n eps) (when (>= n 0) (do ((x (/ n 2.0) (/ (+ x (/ n x)) 2.0))) ((< (abs (- (* x x) n)) eps) x)))) 它给了我单

这是我之前发布的一篇文章的后续文章。很抱歉,这可能是一个基本的Lisp概念,但我还没有掌握它

对于这个问题,我使用的是
gnuclisp2.49(2010-07-07)

假设我有以下函数,它通过牛顿法简单地确定平方根:

(defun sr (n eps)
  (when (>= n 0)
    (do ((x (/ n 2.0) (/ (+ x (/ n x)) 2.0)))
      ((< (abs (- (* x x) n)) eps)
       x))))
它给了我单精度浮点(默认值)。有道理。由于精度不足,如果我将
eps
设置得太小,它将无法正常工作并进入无限循环:

> (sr 2 0.00000001)
[just sits there...]
如果我用双精度值调用它,仍然会得到单精度结果:

> (sr 2.0d0 0.00001d0)
1.4142157
> (sr 2.0d0 0.00000001d0)
[just sits there...]
但如果我重新定义我的函数如下:

> (sr 2 0.00001)
1.4142157
(defun sr (n eps)
  (when (>= n 0)
    (do ((x (/ n 2.0d0) (/ (+ x (/ n x)) 2.0d0)))
      ((< (abs (- (* x x) n)) eps)
       x))))
现在,由于精度提高,给它送一个更小的
eps

> (sr 2 0.00000001)
1.4142135623746899d0
所以我的问题是:函数应用的精度是否完全由我在它包含的算术表达式中使用的常量中指定的精度驱动?如果是的话,如果函数中没有常数呢?那么,是什么决定了计算的精度和结果呢


附录


我刚刚在SBCL 1.0.57-1.fc17上重新测试了这一点,根据@JoshuaTaylor在评论中引用的文档,我得到了更多的预期结果。

在我看来,这是CLISP与ANSI CL标准的不兼容

ANSI CL标准要求结果为所有参数的最大类型:

CL-USER 20 > (/ 2.0d0 2.0)
1.0D0
CLISP提供:

[4]> (/ 2.0d0 2.0)
1.0
这应该是一个双浮点数

您可以在CLISP中将其更改为标准ANSI CL行为

[9]> CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*
NIL
[10]> (setf CUSTOM:*FLOATING-POINT-CONTAGION-ANSI* t)
T
[11]> (sr 2.0d0 0.00001d0)
1.4142156862745097d0
现在它返回所需的结果


请参阅CLISP手册:

在我看来,这是CLISP与ANSI CL标准的不兼容

ANSI CL标准要求结果为所有参数的最大类型:

CL-USER 20 > (/ 2.0d0 2.0)
1.0D0
CLISP提供:

[4]> (/ 2.0d0 2.0)
1.0
这应该是一个双浮点数

您可以在CLISP中将其更改为标准ANSI CL行为

[9]> CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*
NIL
[10]> (setf CUSTOM:*FLOATING-POINT-CONTAGION-ANSI* t)
T
[11]> (sr 2.0d0 0.00001d0)
1.4142156862745097d0
现在它返回所需的结果


请参阅CLISP手册:

中说,“数值函数的结果是该函数所有浮点参数中最大格式的浮点。”这听起来像是如果你放入双浮点,你应该得到双浮点。你的行为很有趣…@JoshuaTaylor我更新了我的问题,表明我正在使用GNU CLISP 2.49。请看我的答案。这在CLISP中有一个设置。表示:“数值函数的结果是该函数所有浮点参数中最大格式的浮点。”这听起来像是,如果放入双浮点,则应取出双浮点。你的行为很有趣…@JoshuaTaylor我更新了我的问题,表明我正在使用GNU CLISP 2.49。请看我的答案。这在CLISP中有一个设置。啊。。。我刚刚用SBCL试过了,它确实像预期的那样工作。因此,我同意这一回答。:)那很有趣。我想知道为什么
*浮点传染病-ANSI*
的默认值不是
t
。但这一点文件确实免除了克里普的一些罪责@雷纳,你打败了我;我在谷歌上搜索了CLISP和12.1.4.4,找到了这篇提到设置的帖子:,做得好!那一节读起来很有趣。令人着迷的是,CLISP开发人员对ANSI默认值采取了这种独特的立场(根据他们的解释可以理解)。。。我刚刚用SBCL试过了,它确实像预期的那样工作。因此,我同意这一回答。:)那很有趣。我想知道为什么
*浮点传染病-ANSI*
的默认值不是
t
。但这一点文件确实免除了克里普的一些罪责@雷纳,你打败了我;我在谷歌上搜索了CLISP和12.1.4.4,找到了这篇提到设置的帖子:,做得好!那一节读起来很有趣。CLISP开发人员对ANSI默认值采取了这种独特的立场(根据他们的解释,这是可以理解的),这是非常有趣的。