模块化逆的奇怪Python加速

时间:2017-02-25 14:18:47

标签: algorithm performance python-3.x recursion mod

通常我很懒,并按如下方式计算模块化逆:

def inv(a,m):
    return 1 if a==1 else ((a-inv(m%a,a))*m+1)//a
print(inv(100**7000,99**7001))

但我很想知道传递更多信息的方法,即Bezout定理的解决方案(而不仅仅是其中一个),在实践中会产生更快或更慢的算法:

def bez(a,b):
    # returns [x,y,d] where a*x+b*y = d = gcd(a,b) since (b%a)*y+a*(x+(b//a)*y)=d
    if a==0: return [0,1,b] if b>0 else [0,-1,-b]
    r=bez(b%a,a)
    return [r[1]-(b//a)*r[0],r[0],r[2]]
def inv(a,m):
    r=bez(a,m)
    if r[2]!=1: return None
    return r[0] if r[0]>=0 else r[0]+abs(m)
print(inv(100**7000,99**7001))

我惊讶地发现后者的速度比前者快50倍!但是每个调用都使用几乎相同数量的递归调用和1个整数除法和1个模运算,并且操作数的位长平均大约是前者的两倍(因为所涉及的参数是相同的),所以我只期望它的时间复杂度大约是后者的4倍,而不是50倍。

  

那我为什么要观察这种奇怪的加速?

请注意,我使用的是Python 3,我在运行online时观察到了这一点,并在顶部添加了以下代码以阻止Python解释器抱怨超出最大递归深度或堆栈空间:

import resource,sys
sys.setrecursionlimit(1000000)
resource.setrlimit(resource.RLIMIT_STACK,[0x10000000,resource.RLIM_INFINITY])

0 个答案:

没有答案