【问题标题】:How does this two-function recursion work? [closed]这个双函数递归是如何工作的? [关闭]
【发布时间】:2021-11-14 15:24:29
【问题描述】:

我已经尝试理解了大约 2 个小时,但我仍然感到困惑。

def is_even(n):
    if n==0:
       return True
    else:
       return is_odd(n-1)

def is_odd(n):
    return not is_even(n)

【问题讨论】:

  • 什么特别让你困惑?
  • 递归一开始可能很难理解。一旦你举出例子并一遍又一遍地浏览代码,你就会弄明白。
  • 这是一个学习递归的糟糕例子。这个任务should be done with modulo(%),不是重复减法,也绝对不是递归减法。对于 n=499 或更大,它实际上会崩溃。在这里提问之前,请先尝试阅读教程,例如this one from RealPython
  • @wjandrea 这可能是一个家庭作业,教师可能要求创建递归函数而不是使用模数。代码可能不是为了效率,而是为了学习目的。我听说候选人在面试中也被问到这个问题。
  • @wjandrea 我和你在一起。这不是教授递归的最佳练习。阶乘是学习记忆和递归的好方法。现实情况是,一些老师和面试官举了这个例子。

标签: python python-3.x recursion


【解决方案1】:

要使递归函数成功(不是无限递归),它需要两件事:

  1. 递归函数必须始终具有基本情况(或退出条件)
  2. 递归函数必须倾向于基本情况(或者换句话说,它必须迭代地将问题的“大小”减小到同一问题的较小版本,直到达到基本情况)

此函数的基本情况是当n == 0is_even() 函数返回一个值True,而不是返回函数调用的结果。

is_even() 所做的是调用自身,并使用不断减小的 n 值,直到 n == 0 在此时返回 True,因为它已达到基本情况。它起作用的原因是因为每个递归调用都将布尔值not 添加到其返回值。

因此,对该函数的调用将在True 前面返回偶数个否定或奇数个否定。如果有偶数个否定,那么每一对都会抵消,你最终会得到True。如果有奇数个否定,那么您将在 True 前面得到最后一个 not

例子:

is_even(2) = not is_even(1)
           = not (not is_even(0))  # base case, returns True
           = not (not True)
           = not (False)
           = True
is_even(3) = not is_even(2)
           = not (not is_even(1))
           = not (not (not is_even(0)))  # base case, returns True
           = not (not (not True))
           = not (not (False))
           = not (True)
           = False

请注意,您的代码的编写方式可以通过最初使用任何负整数(或任何非整数浮点数)调用 is_even() 来无限递归。这将引发RecursionError

这是因为即使is_even() 满足第一条规则(必须有一个基本情况),它在某些情况下违反了第二条规则(它并不总是将问题简化为“自身的较小版本”。在在这种情况下,通过调用is_even(-1),每次递归调用都会从这个值中减去 1,从而扩大问题的规模:

is_even(-1) = not is_even(-2)
            = not (not is_even(-3))
            = not (not (not is_even(-4)))
            .
            .
            .

非整数浮点数也会发生同样的事情:

is_even(1.1) = not is_even(0.1)
             = not (not is_even(-0.9))
             = not (not (not is_even(-1.9)))
             .
             .
             .

【讨论】:

    【解决方案2】:

    在递归中,您不断循环执行相同的操作,直到某个条件中断该循环。让我们用一个例子来看看你的代码。

    1 是奇数还是偶数?

    def is_even(n):
        if n==0:
           return True
        else:
           return is_odd(n-1)
    
    def is_odd(n):
        return not is_even(n)
    
    print(is_even(1))
    

    在这个例子中,

    • def is_even(n) 被调用。 n = 1
    • n不为0,所以达到else条件
    • 调用了返回 is_odd(0) 但我们不知道 is_odd 是什么
    • (A) 因此,is_odd(0) 在返回发生之前被调用
    • ..(B) is_odd 返回 is_even(0) 的倒数,但我们必须找出 is_even(0) 是什么
    • .... is_even(0) 检查 n = 0。它是。所以,它返回 True
    • ..(B) 为真。它返回 True 的倒数,即 False。 (B) 返回错误
    • (A) 收到 False 并将其返回打印
    • print 打印错误

    现在尝试遵循与 2 相同的逻辑。您将经历比上述更多的步骤。

    【讨论】:

    • 我认为这是 OP 认为最有帮助的解释。 +1
    猜你喜欢
    • 2020-08-18
    • 2016-11-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    相关资源
    最近更新 更多