简体   繁体   中英

Prime Number Recursion- How Does It Work? (Python)

I was wondering how this program knows if a number is prime or not. I understand that it checks for remainders to find even numbers to divide by but how does it know that a number has only 2 factors? I'm new to the concept of recursion so a explanation of the steps would be helpful thank you.

Code

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)

Source

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

Lines: 184 to 194

It checks whether there's any number from m - 1 down to 1 that divides m, it doesn't check just even numbers.

EG, for RecIsPrime(10) you will have these nested functions call:

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 != 0 is false , so the right hand side of the and won't be evaulated. PrimeHelper(10, 5) will return false and doesn't continue the recursion.
In PrimeHelper(10, 6) you get 10 % 6 != 0 to be true , but we've just seen PrimeHelper(10, 5) to be false so this will return false as well, and so will all the other calls.

This code is a tail recursion case, ie it can be seen as a recursive way to perform iteration. Note that Python doesn't actually interpret it that way (which would be an optimisation), but it is still helpful to see it like that:

See how every recursive call of PrimeHelper has the same value for m , but has a value for j that is one less compared to the value it had in the previous call.

So the code is comparable to this variant:

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

In this variant every iteration corresponds to a recursive call in the original code. Note that return False breaks the chain, which is done by m % j != 0 in the original code, ie there it serves two purposes:

  1. Return False
  2. Don't call PrimeHelper anymore

It is important to note that the two variants do not behave the same way when you call RecIsPrime with an argument of 1 or less. In those cases the recursive code can produce a "division by zero" error (when RecIsPrime(1) ) or recurse for ever (eg RecIsPrime(-1) or any lesser value). This is a bug. To correct it change:

return PrimeHelper(m, m -1)

by

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

which also fixes the case for 1: it is more than just "debatable" whether 1 is prime or not: it is definitely not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM