繁体   English   中英

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

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

我必须使用递归找出 number(N) 是否是素数,不允许循环。 我尝试将使用 for 循环的常用代码转换为递归代码,但它的行为不一样。 此功能包含在另一个功能中,该功能是另一个功能的一部分。 只应使用和传递参数 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

我相信这个错误在这里的某个地方。

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

这是我尝试转换的代码。

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")

您的解决方案很接近,只需进行一些更改即可使其正常工作。

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

您没有给出调用此函数的任何示例,但我认为它总是a 2 的形式调用,因为任何其他值都没有意义。 所以如果你像这样运行上面的函数,你应该得到正确的输出:

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

我认为您对递归的工作方式有误解,您在函数体中分配了这个prime变量,但从未对它做任何事情。 也许你的困惑来自对 Python 中作用域的误解。 prime变量不会在调用之间“共享”,它只会每次都创建一个新的prime

编辑:没有意识到您希望该函数仅打印出素数,如果它是素数,则相应地更改了代码。

你的函数有时会返回一些东西,有时什么也不返回——它应该是一个或另一个,而不是两者。 在这种情况下is_prime()看起来像一个布尔函数,所以它应该返回 True 或 False。 我们将打印留给调用者:

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)

把事情简单化。 仔细考虑每一个可能的情况。 避免不必要地增加缩进深度,这会使您的代码更加复杂。

上述解决方案试图通过避免偶数(除数和数字)并将除数限制为数字的平方根来加速素数检测。 这很重要,因为如果没有这些优化,递归解决方案可能会在 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))

如果一个数只能被自身和 1 整除,则该数称为素数。因此从 2 迭代到 n-1,如果 n 可被 (2,3,4,..n-1) 中的任何一个整除,则返回 False。
如果j == n则 (2,3,4...n-1) 中没有这样的数可以被 n 整除,因此它是素数。

由于目标是打印数字以防它是素数,让我们先做那部分。 您的代码中已经有了它的条件,但没有打印:

if a >= N:
    print(N)
    return

接下来我们需要处理所有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)

首先检查, if N == 2是不必要的,因为在此之前已经有一个块处理所有N为素数的情况,因此可以将其删除。 也就是说,拥有它不会造成任何伤害。

检查N是否可被a整除的下一个块应该终止递归。 既然你知道N不是素数,你就应该停在那里。

N不能被a整除时执行的最终块应该执行递归。 就目前而言,一旦N % a != 0递归停止,这显然是错误的。

这是具有上述修改和清理的工作示例:

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

打印给定范围之间的素数列表

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)

如果您不想使用辅助功能

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 

此外,您不需要检查 (1 - N) 之间的所有数字,而只需要检查 sqrt(n)。 您可以将迭代方法更改为

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 循环

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

由于有很多很酷的尝试来改进代码,我试了一下,这是我使用递归查找数字是否为素数的最佳解决方案。 您必须自己添加打印语句或任何其他逻辑,但主要思想非常简单:

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)
  • 该函数应仅使用一个参数调用-要检查的数字-,因为它将第二个设置为第一个检查点;
  • 如果数字是一个或当前检查点(在第一种情况下,一个或两个),那么它是一个素数;
  • 如果该数字可以被当前检查点整除,则返回 false,因为它不是质数;
  • 如果该数字不属于上述任何一种情况,请再次调用该函数,但这次将检查点增加一;

重复此操作,直到数字落入其中一种情况 - 最坏的情况下,数字是素数:第一种情况(n == 检查点)

暂无
暂无

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

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