lisp - 了解函数中的数字数据类型

标签 lisp common-lisp clisp

这是 question on double-float 的后续内容我之前发布的。对于这可能是 Lisp 的基本概念,我深表歉意,但我还没有掌握它。

对于这个问题,我使用GNU CLISP 2.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))))

我可以这样调用它:

> (sr 2 0.00001)
1.4142157

它给了我单精度 float (默认值)。说得通。由于缺乏精度,如果我将 eps 设得太小,它就无法正常运行并进入无限循环:

> (sr 2 0.00000001)
[just sits there...]

如果我用 double 值调用它,我仍然得到单精度结果:

> (sr 2.0d0 0.00001d0)
1.4142157
> (sr 2.0d0 0.00000001d0)
[just sits there...]

但是如果我按如下方式重新定义我的函数:

(defun sr (n eps)
  (when (>= n 0)
    (do ((x (/ n 2.0d0) (/ (+ x (/ n x)) 2.0d0)))
      ((< (abs (- (* x x) n)) eps)
       x))))

然后,无论我如何提供它,我都会得到 double :

> (sr 2 0.00001)
1.4142156862745097d0

现在由于精度提高,可以给它提供更小的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

这应该是一个双 float 。

您可以在 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 手册:12.2.4.1. Rule of Float Precision Contagion

关于lisp - 了解函数中的数字数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21356845/

相关文章:

macros - 宏中的 clojure 引号和代字号

lisp - 将可变对插入可变列表

common-lisp - 类型谓词

LISP 检查列表是否对称而没有反向

lisp - 普通口齿不清 : unable to load a file into the Lisp interpreter

c# - 面向 C# 开发人员的 Common Lisp IDE?

lisp - CLISP 终端错误 : Invalid byte sequence

common-lisp - 用Lisp编写Lambda表达式

lisp - 编写一个以数字为参数的函数并构造一个列表

lisp - 在 autocad 的连接点上打破多段线 - 任何 lisp 函数?