在递归函数中,如何控制函数调用的次数。即递归函数对其自身进行调用的次数

时间:2019-05-09 13:07:20

标签: python python-3.x

我现在有2个函数,其中之一是编写一个简单的递归函数,该函数将在n个步骤中计算指数

第二个函数是我的主要问题,是n / 2个步骤。我对如何协商或控制由n表示的递归调用数感到困惑。

这是一个作业问题,我不允许使用任何形式的循环,只有在那时才允许使用“ while”和“ for”循环,所以请对我轻松一点,因为我知道它看起来很简单。

def simple_recursive_power(x, n):
    print("n="+str(n))
    if n ==1:
        return x
    else:
        return x* simple_recursive_power(x,n-1)

print("the simple recurse method="+ str(simple_recursive_power(3,3)))

""the above works, the one below is working the wrong way""

def advanced_recursive_power(x, n):
    print("n="+str(n))
    if n <= 1:
        return x

    else:
        return x * advanced_recursive_power(x, n-1/2)


print("advanced recursion="+ str(advanced_recursive_power(3,3)))

2 个答案:

答案 0 :(得分:1)

占据一半周期的更好的指数函数不仅需要调整N,还需要更好的算法。

简单的指数是这样的:走N步,每一步乘以X。

如果要将步数减半,需要注意的关键细节是,如果乘以X * X,则一次要两个步。。

def advanced_recursive_power(x, n):
    print("n="+str(n))
    if n == 0:
        return 1
    elif n == 1:
        return x
    else:
        return x * x * advanced_recursive_power(x, n - 2)

现在,这减少了函数调用的次数,但减少了乘法的次数:例如,对于N = 7,我们从X * X * X * X * X * X * XX * (X * X) * (X * X) * (X * X)。如果我们可以预先计算X * X,那么实际上也可以减少乘法运算...这将计算(X2 = X * X); X * X2 * X2 * X2,它有四个乘法,而不是七个:

def super_advanced_recursive_power(x, n):
    print("n="+str(n))
    if n % 2 == 0:
        start = 1
    else:
        start = x
    return start * simple_recursive_power(x * x, n // 2)

答案 1 :(得分:0)

如果您接通电源,则可以大大减少步骤数:

def arp(x, n):
    """Advanced recursive power equivalent to x ** n"""
    print('#', x, n)
    if n == 0:
        return 1
    elif n == 1:
        return x
    elif n % 2:  # odd exponential
        return x * arp(x * x, (n - 1) // 2)
    else:  # even exponential
        return arp(x * x, n // 2)

这仅需O(log n)个步骤。

>>> arp(3, 15)
# 3 15
# 9 7
# 81 3
# 6561 1
14348907

这等效于将加法表示为一系列的减量和增量:

def recursive_add(x, y):
    if y == 0:
       return x
    return (x + 1, y - 1)

这使用了x + y == (x + 1) + (y - 1)。同样,对于幂,关系x ** n == (x * x) ** (n / 2)成立。虽然加法(线性)相当慢,但幂(指数)却很快。

这种利用甚至可以增强重复条款的功能。例如,2**8可以写为((2 * 2) * (2 * 2)) * ((2 * 2) * (2 * 2))-注意术语2 * 2(2 * 2) * (2 * 2)的重复方式。我们可以将2**8重写为((2 ** 2) ** 2) ** 2。这恰好是指数的最后一项递归计算的结果。

对于奇指数,我们有一个问题,例如从2 ** 34 ** 1.5。因此,我们使用x ** n == x * (x ** (n - 1))从奇数到偶数。由于我们排除了n == 1的情况,因此我们知道n >= 3,因此直接进行x * x, (n-1) // 2是安全的。

最终结果是,每一步n减半,而不仅仅是一次。