使用递归计算大数的幂
Posted
技术标签:
【中文标题】使用递归计算大数的幂【英文标题】:Using recursion to calculate powers of large digit numbers 【发布时间】:2015-12-10 20:32:59 【问题描述】:我们的目标是使用递归计算大数提升到其他大数,例如,100 位数字提升到另一个 100 位数字。
我的计划是递归计算 exp/2,其中 exp 是指数,并根据 exp 是偶数还是奇数进行额外计算。
我当前的代码是:
def power(y, x, n):
#Base Case
if x == 0:
return 1
#If d is even
if (x%2==0):
m = power(y, x//2, n)
#Print statment only used as check
print(x, m)
return m*m
#If d is odd
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
我遇到的问题是它进行了太多计算,我正在努力弄清楚如何解决它。例如,2^3 返回 64,2^4 返回 256,2^5 返回 1024,依此类推。它计算 m*m 的次数太多了。
注意:这是求解大数模的一部分。我正在严格测试我的代码的指数部分。
【问题讨论】:
您的缩进(至少在问题方面)不正确。 此外,太多是什么意思。请提供一个例子,并说明您认为哪些语句不应该出现...... 哦,输入的时候一定没有意识到,谢谢! @CommuSoft:除非你有很多字节的 RAM,否则 bignums 不会削减它。 @jboyda5,你不需要写这个函数。使用内置的pow()
。
【参考方案1】:
首先,您的实现有一个奇怪的地方:您使用了一个从未使用过的参数n
,而只是继续传递并且您从不修改。
其次第二次递归调用不正确:
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
如果你做数学,你会看到你返回:(y yx//2)2=y2*(x //2+1)(注意//
而不是/
),因此一个y 太多了。为了正确执行此操作,您应该将其重写为:
else:
m = power(y, x//2, n)
#Print statement only used as check
print(x, m)
return y*m*m
(因此从m
部分中删除y*
并将其添加到return
语句中,这样它就不是平方的)。
这样做将使您的实现至少在语义上合理。但它不会解决性能/内存方面的问题。
您的comment 明确表示您想对结果进行取模,所以这可能是 Project Euler?
策略是利用模在乘法下闭合的事实。换句话说,以下成立:
(a b) mod c = ((a mod c) * (b mod c)) mod c
您可以在您的程序中使用它来防止生成巨大的数字,从而处理需要很少计算工作量的小数字。
另一个优化是您可以简单地在参数中使用正方形。所以更快的实现是这样的:
def power(y, x, n):
if x == 0: #base case
return 1
elif (x%2==0): #x even
return power((y*y)%n,x//2,n)%n
else: #x odd
return (y*power((y*y)%n,x//2,n))%n
如果我们用这个函数做一个小测试,我们看到两个结果对于小数字是相同的(pow()
可以在合理的时间/内存中处理):(12347**2742)%1009
返回787L
和@987654334 @787
,所以它们产生了相同的结果(当然这不是证明),两者是等价的,只是一个过滤掉明显错误的简短测试。
【讨论】:
感谢所有帮助。我假设通过将 y 乘以 power(y, x, n) 将产生与在 return 语句中乘以 y 相同的结果。【参考方案2】:根据这个问题的 c 版本,这是我的方法,它适用于正面和负面的暴露:
def power(a,b):
"""this function will raise a to the power b but recursivelly"""
#first of all we need to verify the input
if isinstance(a,(int,float)) and isinstance(b,int):
if a==0:
#to gain time
return 0
if b==0:
return 1
if b >0:
if (b%2==0):
#this will reduce time by 2 when number are even and it just calculate the power of one part and then multiply
if b==2:
return a*a
else:
return power(power(a,b/2),2)
else:
#the main case when the number is odd
return a * power(a, b- 1)
elif not b >0:
#this is for negatives exposents
return 1./float(power(a,-b))
else:
raise TypeError('Argument must be interfer or float')
【讨论】:
以上是关于使用递归计算大数的幂的主要内容,如果未能解决你的问题,请参考以下文章