计算阶乘的快速算法
Posted
技术标签:
【中文标题】计算阶乘的快速算法【英文标题】:Fast algorithms for computing the factorial 【发布时间】:2010-12-17 14:30:11 【问题描述】:我发现this page 描述了一些计算阶乘的算法。不幸的是,解释很简洁,我不想逐行筛选源代码来理解算法背后的基本原理。
谁能指出我对这些(或其他快速)计算阶乘算法的更详细描述?
编辑:This page 描述了素数分解方法,这是所有性能最佳的阶乘算法所共有的技术。它还包含一些不错的 Python 示例代码。作者链接到 a description of binary splitting 并引用了 Journal of Algorithms 中的一篇文章(“On the Complexity of Calculating Factorials”),如果我能得到它的话,看起来很有希望。
【问题讨论】:
如果你的阶乘很大,并且你想要一个近似值,不要忘记斯特林的近似值。我注意到该页面中没有提到它。 en.wikipedia.org/wiki/Stirling%27s_approximation @Rooke:我正在寻找精确计算大阶乘......也许我应该在我的问题中更清楚。不过感谢您的建议! 你也可以试试我的Fast exact bigint factorial 【参考方案1】:查看 Richard Fateman 的 paper (PDF link)。代码示例在 Lisp 中,但无论如何,大部分秘密归结为最小化您必须执行的 bignum(任意精度整数)计算的数量。
当然,如果您不需要/没有 bignums,那是微不足道的;查找表或简单的循环都可以。
编辑:如果您可以使用近似答案,您可以通过将log(k)
与k = 2 ... n
相加或使用古老的Stirling approximation 直接计算阶乘的对数。您希望尽可能使用对数以避免溢出;特别是,斯特林近似的幼稚应用会在很多不需要的地方溢出。
【讨论】:
+1:那篇论文很有帮助(虽然我的 Lisp 有点生疏)。不幸的是,看起来 Luschny 是更复杂算法的首选人,所以我可能无法阅读他的源代码。【参考方案2】:还有另一种方法。此方法详细here 将乘法量减半,只需一点点加法和减法。您可能希望显示第一种方法,如果您能理解,显示的第二种方法很有趣。
【讨论】:
【参考方案3】:十多年后,我想提供一种 Python 方法,其灵感来自于您对乘法 factorial(n) * n+1
感兴趣,基本情况是 0
和 1
,其结果是 1
,那么:
def fact_var(num):
a, b, i = 1,2,2 # base cases and our i counter.
while i < num: # if i is equal to num, we're done, last product will be at return.
c = a * b # start to multiply and save in c.
i+=1 # add 1 to i because we want to multiply next number with c (in the next iteration).
a, b = c, i # update variables to the next iteration.
return a * b if num > 1 else 1 # last product occurs here is num is greater than 1.
print(fact_var(100000))
对于 100 000 的阶乘,它在我的机器中最多需要 5 秒,我希望它能够为文档和即将到来的观众服务!
附言。同样的想法对计算斐波那契很有用,它是求和而不是乘法。
【讨论】:
以上是关于计算阶乘的快速算法的主要内容,如果未能解决你的问题,请参考以下文章