为什么对于大的整数,计算阶乘的“分而治之”方法如此之快?

时间:2012-12-01 07:06:37

标签: python factorial divide-and-conquer

我最近决定研究大整数的因子算法,这种“分而治之”的算法比简单的迭代方法和素因子方法更快:

def multiply_range(n, m):
    print n, m
    if n == m:
        return n
    if m < n:
        return 1
    else:
        return multiply_range(n, (n+m)/2) * multiply_range((n+m)/2+1, m)

def factorial(n):
    return multiply_range(1, n)

我理解为什么算法有效,它只是递归地将乘法分成更小的部分。我不明白为什么这种方法更快。

2 个答案:

答案 0 :(得分:5)

与@ NPE的答案相反,您的方法 更快,仅适用于非常大的数字。 对我来说,我开始看到输入分裂和征服方法变得更快~10 ^ 4。在10 ^ 6及以上,没有比较传统的循环失败。

我不是硬件乘法器方面的专家,我希望有人可以对此进行扩展,但我的理解是乘法在数字上以数字方式完成,就像我们在小学里教的那样。

传统的阶乘循环将从较小的数字开始,结果不断增长。最后,你用一个相对较小的数字来处理一个巨大的数字,由于数字不匹配而计算成本很高。

离。比较

reduce(operator.mul, range(1,10**5))
reduce(operator.mul, range(10**5,1,-1))

第二个是较慢的,因为结果快速增长,导致更快的计算成本。

对于大数字,您的方法比其中任何一个都要快几个数量级,因为它将阶乘分为类似大小的部分。子结果具有相似的数字位数并且乘以更快。

答案 1 :(得分:4)

简短的回答是你错了。它不是很快:

In [34]: %timeit factorial(100)
10000 loops, best of 3: 57.6 us per loop

In [35]: %timeit reduce(operator.mul, range(1, 101))
100000 loops, best of 3: 19.9 us per loop

换句话说,它比简单的单行程慢约三倍。

对于较小的n值,差异更为显着。