【问题标题】:How do I find a prime number using recursion in Python如何在 Python 中使用递归找到素数
【发布时间】:2016-09-02 21:24:59
【问题描述】:

我必须使用递归找出 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")

【问题讨论】:

  • 函数应该返回什么吗?
  • @hd1,我不同意重复通话。这特别要求使用没有任何循环的递归解决方案。该解决方案显然使用了循环。
  • 不,如果它是素数,它只是为了打印(N)。这个函数是另一个函数的一部分。 @niemmi

标签: python python-3.x recursion primes


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您的函数有时会返回 something 有时会返回 nothing —— 它应该是一个或另一个,而不是两者。在这种情况下,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。

    【讨论】:

      【解决方案3】:
      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 整除,因此它是素数。

      【讨论】:

        【解决方案4】:

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

        if a >= N:
            print(N)
            return
        

        接下来我们需要处理N &gt; 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)
        

        【讨论】:

          【解决方案5】:

          打印给定范围内的素数列表

          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)
          

          【讨论】:

          • 添加一些描述,使其更易于理解,以及为什么它很好
          【解决方案6】:
          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
          

          【讨论】:

            猜你喜欢
            • 2015-10-09
            • 1970-01-01
            • 2017-01-19
            • 1970-01-01
            • 2017-05-20
            • 2020-07-03
            • 1970-01-01
            • 2021-01-14
            • 1970-01-01
            相关资源
            最近更新 更多