这个递归语句如何工作?

时间:2016-05-03 18:58:27

标签: python

我有两个递归语句做同样的事情,我理解第一个如何工作,但我对第二个案件感到困惑。

1)

def recurPower(base, exp):
 '''
 base: int or float.
 exp: int >= 0

 returns: int or float, base^exp
 '''
 # Base case is when exp = 0
 if exp <= 0:
   return 1

 # Otherwise, exp must be > 0, so return 
 #  base* base^(exp-1). This is the recursive case.
 return base * recurPower(base, exp - 1)

这是第一种情况,虽然它正在回忆起它仍然留下一个变量“基础”,每次都围绕该方法相乘。

2)

def recurPowerNew(base, exp):
'''
base: int or float.
exp: int >= 0

returns: int or float; base^exp
'''
# Base case is when exp = 0
if exp <= 0:
    return 1

# Recursive case 1: exp > 0 and even
elif exp % 2 == 0:
    return recurPowerNew(base*base, exp/2)

# Otherwise, exp must be > 0 and odd, so use the second
#  recursive case.
return base * recurPowerNew(base, exp - 1)

在这种情况下,如果它是一个偶数数字,我不明白它是如何工作的,没有像第一种情况那样的变量被采取行动,当数字是偶数时只是不断给自己不同的参数,但它实际上并没有真正解决任何特定的变量,如“基础”。

如果方法中没有主体,参数会返回一个值吗?

2 个答案:

答案 0 :(得分:1)

我们举一个例子:

print recurPowerNew(3, 4)

因此base为3而exp为8.这将属于您关注的情况,并致电:

return recurPower(9, 2)

...也属于同一案例,并致电

return recurPower(81, 1)

啊,哈!这是奇怪的情况。所以这会打电话:

return 81 * recurPower(81, 0)

乘法的第二项是1,所以我们在堆栈中一直返回81。如果您遵循这一点,它也适用于不是2的幂的数字。

关键是,它比第一种方法更有效率 。它将为指数的每位产生一个或两个堆栈帧。第一种方法将生成exponent堆栈帧!

顺便说一句,第二个例子可以通过观察指数是奇数的情况下更有效,减去一个将产生偶数指数,所以我们可以直接处理:

     return base * recurPowerNew(base*base, exp // 2)

(如果使用Python 2,请使用/代替//

答案 1 :(得分:1)

第一个参数不会返回值,函数会返回。

其次,我看到你可能会对递归问题感到困惑。递归并不要求有一个变量&#34; actted&#34;上。只要递归最终到达基本情况,它就会返回一个值。

例如,这里是一个无用的递归函数,它为任何整数返回1。

def foo(n):
  if n <= 1:
    return 1
  else:
    return foo(n-1)
对于任何整数n,

foo将返回1,因为最终通过从整数中减去1,我们将达到n <1的基本情况。 1.

对于递归问题,关键是要考虑基本情况,并确保在每次迭代时都接近基本情况。

在两个递归函数中,基本情况是指数为零。第二个递归公式只是在n为偶数时采用基本情况的快捷方式。对于每个偶数幂,你可以简单地计算基数的平方并将功率减半,因为x ^ n =(x ^ 2)^(n / 2)

通过一个例子可以说清楚。

盯着

recurPowerNew(2, 10)

因为exp = 10,即偶数,第一个返回值将是:

recurPowerNew(2 * 2, 5)

这是利用2 ^ 10 =(2 ^ 2)^ 5的事实。现在我们必须评估新的返回函数。尽管我们只生成了一个新函数,但我们已经朝着exp = 0的基本情况发展了。所以最终我们期望得到一个答案。

现在我们有一个奇数基数,所以返回值将是:

4 * recurPowerNew(4, 4)

现在我们再次拥有一个我们必须评估的功能,但即便如此 它只返回一个新函数。

4 * recurPowerNew(4 * 4, 2)

再一次。

4 * recurPowerNew(16 * 16, 1)

奇怪的功能,所以我们得到另一个因素。

4 * (256 * recurPowerNew(256, 0))

啊现在我们处于基本情况,并且没有更多的递归。

4 * 256 * 1

我们可以评估结果并获得

1024

使这项工作的关键在于,在每次迭代中我们都接近基本情况,并且我们能够做得少得多,因为除以2会比减1更快地减少指数。