计算双浮点数幂时的浮点舍入误差

问题描述 投票:0回答:1

我想开发一个 Common Lisp 解决方案来解决 Leetcode 问题 50。“Pow(x, n)”,其中询问:

“实现 pow(x, n),计算 x 的 n 次方(即 x^n)。”

我的直接解决方案是:

(defun pow (x n)
  (declare (ftype (function (double-float fixnum) double-float) pow))
  (if (zerop n)
      1d0
      (let ((r 1d0))
        (dotimes (i (abs n)) (setf r (* r x)))
        (if (plusp n)
            r
            (/ 1d0 r)))))

(pow 2.1d0 3)
=> 9.261000000000001d0

为什么句号后面的第15位数字是1?如何获得没有舍入误差的结果?

我的 Common Lisp 实现:Linux 上的 SBCL 2.3.4。

floating-point lisp common-lisp
1个回答
0
投票

用浮点数计算并不准确。即使将数字表示为浮点数也是不准确的。 1/3 是 0.3333...,计算机上的浮点数精度有限。

在 Common Lisp 中,我们可以使用整数和有理数进行计算。

你的代码,但更通用:

(defun pow (x n)
  (if (zerop n)
      1
      (let ((r 1))
        (dotimes (i (abs n)) (setf r (* r x)))
        (if (plusp n)
            r
            (/ 1 r)))))

现在你的 2.1 可能意味着 21/10,这是 Common Lisp 中的一个数字。

CL-USER 7 > (pow 21/10 3)
9261/1000

然后我们可以将结果转换为双精度浮点数:

CL-USER 8 > (float * 1.0d0)
9.261D0
© www.soinside.com 2019 - 2024. All rights reserved.