素数递归 - 它是如何工作的? (蟒蛇)

时间:2016-11-05 13:33:02

标签: python function recursion primes primality-test

我想知道这个程序是如何知道数字是否为素数。我知道它会检查余数以找到偶数除以但是它如何知道数字只有2个因子?我是递归概念的新手,所以对步骤的解释会有所帮助,谢谢。

代码

def RecIsPrime(m):
    """Uses recursion to check if m is prime."""
    def PrimeHelper(m, j):
        """Helper Function to iterate through all j less than m up to 1 to look for even divisors."""
        if j == 1:  # Assume 1 is a prime number even though it's debatable.
            return True
        else:
            #do this task if both conditionals are true
            #else break and return false.
            return m % j != 0 and PrimeHelper(m, j - 1)
    return PrimeHelper(m, m -1)

来源

https://github.com/hydrogeologist/LearningPython/blob/master/_recursion%20example%20in%20Python

行:184到194

2 个答案:

答案 0 :(得分:2)

检查是否存在从m - 1到1除以m的任何数字,它不会检查偶数。

EG,对于RecIsPrime(10),您将拥有这些嵌套函数调用:

PrimeHelper(10, 9) = 10 % 9 != 0 and PrimeHelper(10, 8)
↪ PrimeHelper(10, 8) = 10 % 8 != 0 and PrimeHelper(10, 7)
  ↪ PrimeHelper(10, 7) = 10 % 7 != 0 and PrimeHelper(10, 6)
    ↪ PrimeHelper(10, 6) = 10 % 6 != 0 and PrimeHelper(10, 5)
      ↪ PrimeHelper(10, 5) = 10 % 5 != 0 == false

10 % 5 != 0false,因此and的右侧不会被评估。 PrimeHelper(10, 5)将返回false并且不会继续递归 在PrimeHelper(10, 6)中,您10 % 6 != 0true,但我们刚看到PrimeHelper(10, 5)false,所以这也将返回false,并且所有其他电话也是如此。

答案 1 :(得分:0)

此代码是尾递归的情况,即它可以被视为执行迭代的递归方式。请注意,Python实际上并没有那样解释它(这将是一种优化),但它仍然有助于看到它:

查看PrimeHelper的每个递归调用对 m 的值是否相同,但 j 的值与值相比减少了一个在之前的电话会议中。

因此代码与此变体相当:

def RecIsPrime(m):
    for j in range(m-1, 1, -1):
        if m % j == 0:
            return False
    return m > 1

在此变体中,每次迭代都对应于原始代码中的递归调用。请注意return False打破了链,这是由原始代码中的m % j != 0完成的,即它有两个目的:

  1. 返回False
  2. 不要再打电话给PrimeHelper
  3. 值得注意的是,当您使用1或更小的参数调用RecIsPrime时,这两种变体的行为方式不同。在这些情况下,递归代码可以产生"除以零" 错误(当RecIsPrime(1)时)或递归(例如RecIsPrime(-1)或更低的值) )。这是一个错误。要纠正它的变化:

    return PrimeHelper(m, m -1)
    

    通过

    return m > 1 and PrimeHelper(m, m -1)
    

    还修复了1的情况:它不仅仅是"有争议的" 1是否为素数:它绝对不是。