lisp - Euler #2 尝试后出现 Bignum 溢出错误

标签 lisp stack-overflow tail-recursion bignum

我试图解决 Euler Problem 2具有以下尾递归函数:

(defun fib (num)
  (labels ((fib-helper (num a b)
         (cond ((or (zerop num)
                    (eql num 1))
                a)
               (t (fib-helper (decf num)
                              (+ a b)
                              a)))))
    (fib-helper num 1 1)))


(defun sum-even-fib (max)
  (labels ((helper (sum num)
         (cond ((oddp num) (helper sum (decf num)))
               ((zerop num) sum)
               (t (helper (+ sum (fib num))
                          (decf num))))))
    (helper 0 max)))

现在,当我尝试使用函数打印结果时

(defun print-fib-sum (max dir file)
  (with-open-file
      (fib-sum-str
       (make-pathname
         :name file
         :directory dir)
        :direction :output)
    (format fib-sum-str "~A~%" (sum-even-fib max))))

max 值为 4000000 时,出现错误

     ("bignum overflow" "[Condition of type SYSTEM::SIMPLE-ARITHMETIC-ERROR]" nil)

来自 *slime-events*。还有其他方法可以处理数字并打印到文件吗?

最佳答案

首先是几个小问题:

  1. 使用 time而不是 top

  2. Common Lisp 标准不需要尾递归优化。虽然许多实现都这样做,但并非所有实现都优化了所有情况(例如 labels )。

  3. 您的算法是 max 的二次方算法,因为它为所有索引单独计算第 n 个斐波那契数。你应该让它变成线性的。

  4. 您正在计算偶数索引数的总和,而不是 even-valued numbers .

现在,您看到的算术错误:第 4,000,000 个斐波那契数非常大 - 大约 1.6^4M ~ 10^835951。它的length大约是 2,776,968

你确定你的 lisp 可以表示这么大的 bignums 吗?

关于lisp - Euler #2 尝试后出现 Bignum 溢出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18811744/

相关文章:

scheme - 如何反转 Scheme 中列表元素的顺序

javascript - 持久数据结构 : a persistent index?

macros - 可以使用 destructuring-bind 定义 destructuring-setq 吗?

android - Retrofit 2.0.0 Beta2 OkHttpClient 拦截器抛出 StackOverFlowError

c++ - 为什么函数中的局部数组似乎可以防止 TCO?

algorithm - 将线性递归函数重写为尾递归函数

list - 逗号在反引号之外是非法的?

c# - StackOverflowException 未处理 C#

c# - 设置二进制值时属性异常

c - 我不知道如何纠正我的尾递归(原本是常规递归)