计算阶乘的快速算法

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 感兴趣,基本情况是 01,其结果是 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 秒,我希望它能够为文档和即将到来的观众服务!

附言。同样的想法对计算斐波那契很有用,它是求和而不是乘法。

【讨论】:

以上是关于计算阶乘的快速算法的主要内容,如果未能解决你的问题,请参考以下文章

如何快速的计算出一个数的n次方

算法-排序

计算快速排序算法中组件明智比较的数量。

谁能解释这个计算大阶乘的算法?

快速幂取模算法

重复计算百分位数的快速算法?