簡體   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