简体   繁体   English

如何在 Python 中使用递归找到素数

[英]How do I find a prime number using recursion in Python

I have to find out whether number(N) is a prime or not using recursion, no loops are allowed.我必须使用递归找出 number(N) 是否是素数,不允许循环。 I've tried converting the usual code that uses a for loop to a recursive one, but it's not behaving the same.我尝试将使用 for 循环的常用代码转换为递归代码,但它的行为不一样。 This function is included in another function, which is part of another function.此功能包含在另一个功能中,该功能是另一个功能的一部分。 only parameters a and N should be used and passed Here is my function.只应使用和传递参数 a 和 N 这是我的函数。

a=2
def is_prime(a,N):
prime = True
if N <=1:
    return 
else:
    if a >= N:
        return 
    else:
        if N == 2: 
            prime = True
            print(N)
            return 
        elif (N % a) == 0:
            prime = False
            return is_prime(a+1,N)
        else:
            prime = True
            print(N)

return

I believe the bug is somewhere here.我相信这个错误在这里的某个地方。

elif (N % a) == 0:
            prime = False
            return is_prime(a+1,N)
        else:
            prime = True
            print(N)

Here is the code I tried to convert.这是我尝试转换的代码。

if num > 1:
   for i in range(2,num):
      if (num % i) == 0:
         print(num,"is not a prime number")
         print(i,"times",num//i,"is",num)
         break
   else:
      print(num,"is a prime number")

else:
   print(num,"is not a prime number")

Your solution is close, with just a few changes needed to make it work.您的解决方案很接近,只需进行一些更改即可使其正常工作。

def is_prime(a,N):
    print(a, N)
    if N <= 1:
        return 
    else:
        if a >= N:
            print(N)
        else:
            if N == 2: 
                print(N)
            elif (N % a) == 0:
                return False
            else:
                return is_prime(a+1,N)

    return False

You didn't give any examples of calling this function, but I assume it's always called with a being 2, since any other value wouldn't make sense.您没有给出调用此函数的任何示例,但我认为它总是a 2 的形式调用,因为任何其他值都没有意义。 So if you run the above function like so, you should get the right output:所以如果你像这样运行上面的函数,你应该得到正确的输出:

print(is_prime(2, 7))  => True
print(is_prime(2, 4))  => False
print(is_prime(2, 37)) => True

I think you have a misunderstanding of how recursion works, you're assigning this prime variable in the body of the function, but never doing anything with it.我认为您对递归的工作方式有误解,您在函数体中分配了这个prime变量,但从未对它做任何事情。 Maybe your confusion comes from a misunderstanding of scopes in Python.也许你的困惑来自对 Python 中作用域的误解。 That prime variable will not be 'shared' across invocations, it will just create a new prime every time.prime变量不会在调用之间“共享”,它只会每次都创建一个新的prime

EDIT: Didn't realize you wanted the function to just print out the prime if it's a prime, changed the code accordingly.编辑:没有意识到您希望该函数仅打印出素数,如果它是素数,则相应地更改了代码。

Your function sometimes returns something and sometimes returns nothing -- it should be either all one or the other, not both.你的函数有时会返回一些东西,有时什么也不返回——它应该是一个或另一个,而不是两者。 In this case is_prime() looks like a boolean function so it should return True or False.在这种情况下is_prime()看起来像一个布尔函数,所以它应该返回 True 或 False。 We'll leave the printing to the caller:我们将打印留给调用者:

def is_prime(N, a=3):

    if N == 2:  # special case
        prime = True
    elif N <= 1 or N % 2 == 0:  # too small or even
        prime = False
    elif a * a > N:  # tried all divisors to sqrt, must be prime
        prime = True
    elif (N % a) == 0:  # divides evenly, not a prime
        prime = False
    else:  # can't tell yet, recursively try the next (odd) divisor
        prime = is_prime(N, a+2)

    return prime

for x in range(100):
    if is_prime(x):
        print(x)

Keep it simple.把事情简单化。 Think through each possible case.仔细考虑每一个可能的情况。 Avoid increasing the indention depth unnecessarily, it makes your code more complicated.避免不必要地增加缩进深度,这会使您的代码更加复杂。

The above solution tries to speed up prime detection by avoiding even numbers (both divisor and number) and limiting the divisor to the square root of the number.上述解决方案试图通过避免偶数(除数和数字)并将除数限制为数字的平方根来加速素数检测。 This can matter as without these optimizations, a recursive solution will likely run out of call stack space at around N=1,000 whereas the above should go to N=1,000,000 without expanding the call stack.这很重要,因为如果没有这些优化,递归解决方案可能会在 N=1,000 左右耗尽调用堆栈空间,而上面的解决方案应该在不扩展调用堆栈的情况下达到 N=1,000,000。

def prime(n,j):
    if(n<2):
        return False
    if(j==n):
        return True
    if(n%j==0):
        return False
    return prime(n,j+1)

print(prime(n,2))

A number is called prime if it is only divisible by itself and 1. So iterate from 2 to n-1, if n is divisible by any of (2,3,4,..n-1) return False.如果一个数只能被自身和 1 整除,则该数称为素数。因此从 2 迭代到 n-1,如果 n 可被 (2,3,4,..n-1) 中的任何一个整除,则返回 False。
If j == n then there is no such number from (2,3,4...n-1) divisible by n, Hence it's Prime.如果j == n则 (2,3,4...n-1) 中没有这样的数可以被 n 整除,因此它是素数。

Since the goal is to print the number in case it's prime let's do that part first.由于目标是打印数字以防它是素数,让我们先做那部分。 You've already got a condition for it in your code but there was no print:您的代码中已经有了它的条件,但没有打印:

if a >= N:
    print(N)
    return

Next we need to handle all the cases where N > 1 :接下来我们需要处理所有N > 1的情况:

if N == 2: 
    prime = True
    print(N)
    return 
elif (N % a) == 0:
    prime = False
    return is_prime(a+1,N)
else:
    prime = True
    print(N)

First check, if N == 2 is unnecessary since there's already a block before that handles all the cases where N is prime so it can be removed.首先检查, if N == 2是不必要的,因为在此之前已经有一个块处理所有N为素数的情况,因此可以将其删除。 That said having it there doesn't cause any harm.也就是说,拥有它不会造成任何伤害。

The next block that checks if N is divisible by a should terminate the recursion.检查N是否可被a整除的下一个块应该终止递归。 Since you know that N isn't prime you should just stop there.既然你知道N不是素数,你就应该停在那里。

Final block that gets executed when N is not divisible by a should do the recursion instead.N不能被a整除时执行的最终块应该执行递归。 As it stands now the recursion stops as soon as N % a != 0 which is clearly wrong.就目前而言,一旦N % a != 0递归停止,这显然是错误的。

Here's a working sample with above modifications and cleanup:这是具有上述修改和清理的工作示例:

def is_prime(N, a=2):
    if N <= 1:
        return
    elif a >= N:
        print(N)
    elif N % a != 0:
        is_prime(N, a + 1)

to print the list of prime numbers between a given range打印给定范围之间的素数列表

l=[]
def primenum(x,y):
    global l
    if x==y:
        print(l)
    else:
        m=0
        for i in range(1,x+1):   
            if x%i==0:
                m+=1
        if m==2 or x==1:
            l+=[x,]
            return primenum(x+1,y)
        else:
            primenum(x+1,y)
def is_prime(n):
  def prime_helper(n, x):
    if n == 1:
      return False
    elif n % x == 0:
      return False
    else:
      return prime_helper(n , x+1) if x * x <= n else True 
  return prime_helper(n, 2)

if you don't want to use a helper function如果您不想使用辅助功能

def is_prime(n, x=2):
    if n == 1:
      return False
    elif n % x == 0:
      return False
    else:
      return is_prime(n , x+1) if x * x <= n else True 

Also, you don't need to check all the numbers between (1 - N) but only up to sqrt(n).此外,您不需要检查 (1 - N) 之间的所有数字,而只需要检查 sqrt(n)。 You can change your iterative approach to您可以将迭代方法更改为

for loop for 循环

from math import sqrt 
def is_prime(n):
  if n == 1:
     return False
  for i in range(2, round(sqrt(n)) + 1):
     if n % i == 0:
        return False
  return True

while loop while 循环

def is_prime(n):
  if n == 1:
    return False
  i = 2
  while i * i <= n:
     if n % i == 0:
        return False
     i += 1
  return True

Since there are so many cool attempts to improve the code, I gave it a try and here's my best solution to any case of finding if a number is prime using recursion.由于有很多很酷的尝试来改进代码,我试了一下,这是我使用递归查找数字是否为素数的最佳解决方案。 You'll have to add the print statements or any other logics yourself, but the main idea is quite simple:您必须自己添加打印语句或任何其他逻辑,但主要思想非常简单:

def is_prime_recursive(n, checkpoint = 2):
if n in [1, checkpoint]:
    return True
if n % checkpoint == 0:
    return False
return is_prime_recursive(n, checkpoint + 1)
  • The function should be called with one parameter only - the number to check - , as it sets number two as the first checkpoint;该函数应仅使用一个参数调用-要检查的数字-,因为它将第二个设置为第一个检查点;
  • If the number is one or the current checkpoint (in the first case, one or two) then it's a prime;如果数字是一个或当前检查点(在第一种情况下,一个或两个),那么它是一个素数;
  • If the number is divisible by the current checkpoint, return false, because it's not a prime;如果该数字可以被当前检查点整除,则返回 false,因为它不是质数;
  • If the number doesn't fall into any of the previous cases, call the function again but this time increase the checkpoint by one;如果该数字不属于上述任何一种情况,请再次调用该函数,但这次将检查点增加一;

This is repeated until the number falls into one of the cases - being the worst case the number is a prime: first case (n == checkpoint)重复此操作,直到数字落入其中一种情况 - 最坏的情况下,数字是素数:第一种情况(n == 检查点)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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