Performance 在公共lisp中,计算阶乘的最快方法是什么?

Performance 在公共lisp中,计算阶乘的最快方法是什么?,performance,algorithm,common-lisp,Performance,Algorithm,Common Lisp,在公共Lisp中,计算阶乘的最快方法是什么?对于start,有end-tail递归 (defun factorial (n &optional (acc 1)) (if (<= n 1) acc (factorial (- n 1) (* acc n)))) (defun阶乘(n&可选(附件1)) (如果(您已经实现了计算阶乘的朴素算法。有几种算法具有更好的渐近性能,请参见示例。) 最快的是基于阶乘的素因式分解。也许您的编译器足够聪明,可以将其转换为尾部递归。@kni

在公共Lisp中,计算阶乘的最快方法是什么?对于start,有end-tail递归

(defun factorial (n &optional (acc 1))
(if (<= n 1)
   acc
   (factorial (- n 1) (* acc n))))
(defun阶乘(n&可选(附件1))

(如果(您已经实现了计算阶乘的朴素算法。有几种算法具有更好的渐近性能,请参见示例。)


最快的是基于阶乘的素因式分解。

也许您的编译器足够聪明,可以将其转换为尾部递归。@knivil:也许编译器使其成为循环?我怀疑这个问题是否特定于常见的Lisp;最快的(但如何定义最快的?绝对时间?渐近(O(…)?最少资源密集型?)计算阶乘的方法在大多数语言/实现中可能类似。如果在同一台计算机上使用算法a,则输入n的算法a比算法b快(如CL的vesrion等)算法a比算法b花费更少的计算时间。如果算法a比算法b对每个可能的输入都快,那么n比它快。这是我对更快的看法。这导致了结果表,但这是不可行的。因此,我正在寻找一些可编程的解决方案,可以在PC上使用标准的可购买设备。如果你坚持ct对“每个可能输入”的解释,你不会得到任何合适的答案。适用于大数字的算法可能不适用于小数字。可能执行的操作更少,但需要更多内存,磁盘缓存可能会成为一个问题。有很多类似的问题。你不太可能找到一个比其他算法都好的算法表示所有输入。这就是为什么我们使用O(…)表示法。低于某个阈值时,O(n^2)算法可能比O(n)算法快算法,但不会超过该阈值。但是,对于实际计算而言,更好的渐近性能真的很重要吗?我的猜测是,对于足够大的参数,内存分配的成本将主导实际计算。我不熟悉Lisp;是否不可能在begi中分配必要的内存nning并使用破坏性操作来修改它?我仍然希望内存分配比整数乘法更便宜,整数乘法是任何阶乘算法的缓慢部分。问题是,
biginger
s(在Lisp中实际称为
bignum
s)如果你说实际的整数乘法总是很慢的部分,我会相信你,尽管你必须考虑阶乘算法的复杂性计算通常可能是“盲目的”。对于
BigIntegers
s/
bignum
s的实际成本,通常您必须使用一个独立的库才能在这些任务中获得良好的性能;标准库的实现往往着眼于安全性和可靠性,快速任意精度算法并不是优先考虑的问题。不过,我相信也有例外,Appra有些lisp实现使用GMP,这是非常好的。是的,至少GNU Common lisp(CGL)使用GMP来支持它的
bignum
。它的文档不清楚它是否公开了超出CL标准库要求的任何GMP功能,比如GMP自己的阶乘实现。