我想开发一个 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。
用浮点数计算并不准确。即使将数字表示为浮点数也是不准确的。 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