【发布时间】:2018-08-27 04:07:19
【问题描述】:
我正在尝试创建一个函数prime-factors,它返回一个数字的质因数。为此,我创建了 is-prime 函数和 prime-factors-helper,它将对主要因素进行递归检查。
(defun is-prime (n &optional (d (- n 1)))
(if (/= n 1) (or (= d 1)
(and (/= (rem n d) 0)
(is-prime n (- d 1)))) ()))
(defun prime-factors-helper (x n)
(if (is-prime x) (list x)
(if (is-prime n)
(if (AND (= (mod x n) 0) (< n (/ x 2)))
(append (list n) (prime-factors-helper (/ x n) (+ 1 n)))
(prime-factors-helper x (+ 1 n)))
(prime-factors-helper x (+ 1 n)))))
(defun prime-factors (x)
(prime-factors-helper x 2))
prime-factors 的主要功能似乎适用于某些数字。但是对于大数字,它会返回 "Stack overflow (deep)"。
CL-USER 44 : 5 > (prime-factors 66)
(2 3 11)
CL-USER 49 : 5 > (prime-factors 512)
"Stack overflow (deep)"
你能告诉我为什么它会返回这个错误吗?递归调用有问题吗?
[更新]
我重新定义了is-prime 函数,但显然这不是问题。
(defun is-prime (x &optional (i 2))
(if (= x 1) nil
(if (or (= x 2) (= x 3)) t
(if (<= i (sqrt x))
(if (= (mod x i ) 0) nil
(is-prime x (+ i 1)))
t))))
(defun prime-factors-helper (x n)
(if (is-prime x)
(list x)
(if (is-prime n)
(if (AND (= (mod x n) 0) (<= n (/ x 2)))
(cons n (prime-factors-helper (/ x n) n))
(prime-factors-helper x (+ 1 n)))
(prime-factors-helper x (+ 1 n)))))
优化问题
我还有另一个优化问题。当我有一个大数字(例如123456789)时,我会收到此错误消息Stack overflow (stack size 261120)。我相信因为正确答案是(3 3 3607 3803),所以我的程序一旦用前两个元素(3 3) 构造列表,就需要很长时间才能找到下一个主要因素。如何优化我的代码?
【问题讨论】:
-
这意味着你的递归没有停止。您似乎停止递归的唯一一次是当 x 是素数时。如果这永远不会发生,那么递归将永远持续下去。您是否测试过
is-prime以确保它是正确的? -
@Carcigenicate 是的,我测试过。没错
-
@Carcigenicate 它不是
is-prime函数。我对它的定义不同,但我仍然有完全相同的问题。请检查新的更新,我将is-prime函数的新定义放在哪里 -
那么你需要找出递归没有停止的原因。
(prime-factors 512)也可能只是一个“太大”的问题,无法使用未优化的递归来解决。 -
@Carcigenicate 我解决了。实际上,不仅对于 512。它发生在所有 2 的倍数上。在条件
(if (AND (= (mod x n) 0) (< n (/ x 2)))中,如果数字是 2 的倍数,即使它必须进入,它也永远不会进入这个条件。原因是我放了<。应该是<=。所以(if (AND (= (mod x n) 0) (<= n (/ x 2)))。感谢您的帮助
标签: lisp common-lisp