我可以使用递归替换功率运算符(**)吗?

时间:2017-02-28 21:53:57

标签: python function recursion

在函数定义期间应用递归原理使编码变得更加困难和有趣。

例如,我有这个简单的功能来找到特定数字的力量:

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 

此错误的原因是什么?如何改进我的代码?

2 个答案:

答案 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。