floating-pointlispcommon-lisp

# Floating point rounding error when computing the power of a double-float number

I want to develop a Common Lisp solution to Leetcode problem 50. "Pow(x, n)" which asks:

"Implement pow(x, n), which calculates x raised to the power n (i.e., x^n)."

My direct solution is :

``````(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
``````

Why does it have a 1 at the 15th digit after period ? How can I get the result without this rounding error ?

My Common Lisp implementation : SBCL 2.3.4 on linux.

Solution

• Calculating with floats is not exact. Even representing numbers as floats is not exact. 1/3 is 0.3333..., where a float on a computer has limited precision.

In Common Lisp one can compute with integers and rational numbers.

``````(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)))))
``````

Now your `2.1` might mean `21/10`, which is a number in Common Lisp.

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

We can then convert the result to a double float:

``````CL-USER 8 > (float * 1.0d0)
9.261D0
``````