在函数定义期间应用递归原理使编码变得更加困难和有趣。
例如,我有这个简单的功能来找到特定数字的力量:
def power(a, b):
return a**b
但是如果我决定不使用**
,在这种情况下,我想应用Recursion原则。
我想在块范围内调用相同的函数。 我试过这个:
def power (a, b) :
return a*power(a, b-1)
在打印时输出错误信息
print power(3,3)
Runtime Error: maximum recursion depth exceeded
此错误的原因是什么?如何改进我的代码?
答案 0 :(得分:2)
评论的编纂示例:
def power(a, b):
if b == 0:
return 1
return a * power(a, b - 1)
递归需要一个基本情况 - 这个东西告诉程序“嘿,这是你应该去的那么远。开始回事!”
编辑:对于它的价值,不能保证在Python中很好地实现递归。语言规范没有关于如何处理递归的断言,这意味着深度递归将溢出堆栈。 (这与其他语言形成对比,例如大多数函数式编程语言,其中递归更加优化。)在我的计算机上,使用CPython:
>>> def power(a, b):
... if b == 0:
... return 1
... return a * power(a, b - 1)
>>>
>>> power(1, 10)
1
>>> power(1, 981)
1
>>> power(1, 982)
Traceback (most recent call last):
File "<input>", line 1, in <module>
power(1, 982)
File "<input>", line 4, in power
return a * power(a, b - 1)
File "<input>", line 4, in power
return a * power(a, b - 1)
File "<input>", line 4, in power
return a * power(a, b - 1)
[Previous line repeated 978 more times]
File "<input>", line 2, in power
if b == 0:
RecursionError: maximum recursion depth exceeded in comparison
此外,您的CPU可能比常规乘法更有效地进行取幂,因此以递归方式编写此函数可能比使用内置运算符更慢。
答案 1 :(得分:2)
你既可以利用“分而治之”的策略来提高速度,也可以计算非常大的功率,而不会耗尽堆栈。下面的关系和实现都假设power参数的非负整数值。
您已经注意到a**b == a * a**(b-1)
。但是,当b
为偶数a**b == (a*a)**(b/2)
时,将问题大小减少一半而不是将其减少为1也是如此。与递归一样,您还需要基本情况{{1 }}。把它们放在一起,我们得到:
a**0 == 1
允许我们将def power(a, b):
if b == 0:
return 1
result = power(a * a, b // 2) # calculate the halved problem
return a * result if b & 1 else result # and multiply by a if b is odd
计算为:
114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681344168908984458505602379484807914058900934776500429002716706625830522008132236281291761267883317206598995396418127021779858404042159853183251540889433902091920554957783589672039160081957216630582755380425583726015528348786419432054508915275783882625175435528800822842770817965453762184851149029376。
递归堆栈增长为O(log b),此算法与power(2, 2000)
的比例为11。