[英]Print series of prime numbers in python
我在打印從一到一百的一系列素數時遇到了問題。 我無法弄清楚我的代碼有什么問題。
這是我寫的; 它打印所有奇數而不是素數:
for num in range(1, 101):
for i in range(2, num):
if num % i == 0:
break
else:
print(num)
break
您需要檢查從 2 到 n-1 的所有數字(實際上到 sqrt(n),但是可以,讓它成為 n)。 如果n
能被任何數整除,則它不是素數。 如果一個數字是素數,打印它。
for num in range(2,101):
prime = True
for i in range(2,num):
if (num%i==0):
prime = False
if prime:
print (num)
你可以寫同樣的更短和更 Pythonic:
for num in range(2,101):
if all(num%i!=0 for i in range(2,num)):
print (num)
正如我已經說過的,最好檢查除數不是從 2 到 n-1,而是從 2 到 sqrt(n):
import math
for num in range(2,101):
if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1)):
print (num)
對於像 101 這樣的小數字,這無關緊要,但對於 10**8,差異會非常大。
您可以通過將您檢查的范圍增加 2 來進一步改進它,從而只檢查奇數。 像這樣:
import math
print 2
for num in range(3,101,2):
if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1)):
print (num)
編輯:
由於在第一個循環中選擇了奇數,在第二個循環中無需檢查偶數,因此“i”值可以以 3 開頭並跳過 2。
import math
print 2
for num in range(3,101,2):
if all(num%i!=0 for i in range(3,int(math.sqrt(num))+1, 2)):
print (num)
我支持不假設最佳解決方案並對其進行測試。 下面是我所做的一些修改,以通過@igor-chubin 和@user448810 創建簡單的示例類。 首先讓我說這都是很好的信息,謝謝大家。 但我必須感謝@user448810 的聰明解決方案,結果證明這是迄今為止最快的(在我測試過的解決方案中)。 所以向你致敬,先生! 在所有示例中,我使用 100 萬 (1,000,000) 作為 n。
請隨意嘗試代碼。
祝你好運!
Igor Chubin 描述的方法 1 :
def primes_method1(n):
out = list()
for num in range(1, n+1):
prime = True
for i in range(2, num):
if (num % i == 0):
prime = False
if prime:
out.append(num)
return out
基准測試:超過 272 秒以上
Igor Chubin 描述的方法 2 :
def primes_method2(n):
out = list()
for num in range(1, n+1):
if all(num % i != 0 for i in range(2, num)):
out.append(num)
return out
基准: 73.3420000076 秒
Igor Chubin 描述的方法 3 :
def primes_method3(n):
out = list()
for num in range(1, n+1):
if all(num % i != 0 for i in range(2, int(num**.5 ) + 1)):
out.append(num)
return out
基准: 11.3580000401 秒
Igor Chubin 描述的方法 4 :
def primes_method4(n):
out = list()
out.append(2)
for num in range(3, n+1, 2):
if all(num % i != 0 for i in range(2, int(num**.5 ) + 1)):
out.append(num)
return out
基准: 8.7009999752 秒
user448810 描述的方法5 (我認為這很聰明):
def primes_method5(n):
out = list()
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p]):
out.append(p)
for i in range(p, n+1, p):
sieve[i] = False
return out
基准: 1.12000012398 秒
注意:上面列出的解決方案 5(由 user448810 提出)結果證明是最快、最安靜的創意和聰明的。 我喜歡它。 多謝你們!!
編輯:哦,順便說一句,我覺得沒有必要為值的平方根導入數學庫,因為等價的只是 (n**.5)。 否則,我沒有進行太多編輯,然后將值存儲在輸出數組中以由類返回。 此外,將結果存儲到文件中可能比詳細存儲更有效,並且如果一次只存儲一個文件可以節省大量內存,但由於磁盤寫入會花費更多時間。 我認為總有改進的余地。 所以希望代碼有意義。
2021 年編輯:我知道這已經很長時間了,但我在將 Stackoverflow 鏈接到我的 Codewars 帳戶后返回並查看了我最近累積的積分,這些積分與這篇文章相關聯。 我在原始海報中讀到的東西引起了我對@user448810 的注意,因此我決定通過在附加輸出數組之前過濾掉奇數值來對原始帖子中提到的進行輕微修改。 結果是優化和最新版本的 Python 3.8 的性能要好得多,結果為 0.723 秒(之前的代碼),而使用 1,000,000 的 n 為 0.504 秒。
def primes_method5(n):
out = list()
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p] and sieve[p]%2==1):
out.append(p)
for i in range(p, n+1, p):
sieve[i] = False
return out
將近五年后,我可能知道得更多,但我仍然喜歡 Python,想想它已經這么久了有點瘋狂。 老實說,這篇文章感覺就像是不久前發表的,當時我想我只使用 python 大約一年。 它似乎仍然相關。 瘋狂的。 美好時光。
兩千多年前希臘數學家埃拉托色尼發明的一種更好的方法不是試除法,而是通過反復拋出多個素數來進行篩選。
首先列出從 2 到最大所需素數 n 的所有數字。 然后反復取最小的未交叉數並將其所有倍數划掉; 未交叉的數字是素數。
例如,考慮小於 30 的數字。最初,2 被識別為素數,然后將 4、6、8、10、12、14、16、18、20、22、24、26、28 和 30 划掉。 接下來的 3 被確定為素數,然后 6、9、12、15、18、21、24、27 和 30 被划掉。 下一個素數是 5,因此 10、15、20、25 和 30 被划掉。 等等。 剩下的數是素數:2、3、5、7、11、13、17、19、23 和 29。
def primes(n):
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p]):
print p
for i in range(p, n+1, p):
sieve[i] = False
優化版的篩子分別處理 2 個並且只篩分奇數。 此外,由於所有小於當前素數平方的復合都被較小的素數划掉,所以內循環可以從 p^2 開始,而不是從 p 開始,外循環可以在 n 的平方根處停止。 我會把 優化的版本留給你處理。
break
結束它當前所在的循環。所以,你只檢查它是否能被 2 整除,給你所有奇數。
for num in range(2,101):
for i in range(2,num):
if (num%i==0):
break
else:
print(num)
話雖如此,在 python 中找到素數還有比這更好的方法。
for num in range(2,101):
if is_prime(num):
print(num)
def is_prime(n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
解決上述問題的最佳方法是使用“Miller Rabin Primality Test”算法。 它使用概率方法來確定一個數字是否為素數。 它是迄今為止我遇到過的最有效的算法。
同樣的python實現如下所示:
def miller_rabin(n, k):
# Implementation uses the Miller-Rabin Primality Test
# The optimal number of rounds for this test is 40
# See http://stackoverflow.com/questions/6325576/how-many-iterations-of-rabin-miller-should-i-use-for-cryptographic-safe-primes
# for justification
# If number is even, it's a composite number
if n == 2:
return True
if n % 2 == 0:
return False
r, s = 0, n - 1
while s % 2 == 0:
r += 1
s //= 2
for _ in xrange(k):
a = random.randrange(2, n - 1)
x = pow(a, s, n)
if x == 1 or x == n - 1:
continue
for _ in xrange(r - 1):
x = pow(x, 2, n)
if x == n - 1:
break
else:
return False
return True
Igor Chubin的回答可以改進。 在測試 X 是否為素數時,算法不必檢查直到 X 的平方根的每個數,它只需要檢查直到 sqrt(X) 的素數。 因此,如果它在創建質數列表時引用質數列表,則效率會更高。 下面的函數輸出 b 下所有素數的列表,作為列表方便有幾個原因(例如,當您想知道素數 < b 的數量時)。 通過只檢查素數,它可以在更高的數字上節省時間(與大約 10,000 相比;差異非常明顯)。
from math import sqrt
def lp(b)
primes = [2]
for c in range(3,b):
e = round(sqrt(c)) + 1
for d in primes:
if d <= e and c%d == 0:
break
else:
primes.extend([c])
return primes
我將素數列出到一個條目數字而沒有太多麻煩的方法是使用這個屬性,您可以通過素數的總和獲得任何不是素數的數字。
因此,如果將條目數除以它下面的所有素數,並且它不能被它們中的任何一個整除,那么你就知道你有一個素數。
當然還有更快的獲得素數的方法,但是這個已經表現得很好,特別是因為你沒有將條目數除以任何數字,而只是將素數一直到那個數字。
使用此代碼,我在計算機上設法在不到 4 秒的時間內列出了最多 100 000 個的所有素數。
import time as t
start = t.clock()
primes = [2,3,5,7]
for num in xrange(3,100000,2):
if all(num%x != 0 for x in primes):
primes.append(num)
print primes
print t.clock() - start
print sum(primes)
返回第一個 N 素數的 Python 程序函數模塊:
def get_primes(count):
"""
Return the 1st count prime integers.
"""
result = []
x=2
while len(result) in range(count):
i=2
flag=0
for i in range(2,x):
if x%i == 0:
flag+=1
break
i=i+1
if flag == 0:
result.append(x)
x+=1
pass
return result
解決這個問題的一種更簡單、更有效的方法是存儲之前找到的所有素數,並檢查下一個數字是否是任何較小素數的倍數。
n = 1000
primes = [2]
for i in range(3, n, 2):
if not any(i % prime == 0 for prime in primes):
primes.append(i)
print(primes)
請注意, any
是一個短路函數,換句話說,一旦找到真值,它就會中斷循環。
我們可以使用 sympy 庫制作一個素數列表
import sympy
lower=int(input("lower value:")) #let it be 30
upper=int(input("upper value:")) #let it be 60
l=list(sympy.primerange(lower,upper+1)) #[31,37,41,43,47,53,59]
print(l)
這是一個簡單直觀的檢查它是否是 RECURSIVE 函數中的素數的版本! :) (我是作為 MIT 課程的家庭作業完成的)在 python 中它運行得非常快,直到 1900 年。如果你嘗試超過 1900 年,你會得到一個有趣的錯誤 :) (你想檢查你的數字有多少?電腦能管理嗎?)
def is_prime(n, div=2):
if div> n/2.0: return True
if n% div == 0:
return False
else:
div+=1
return is_prime(n,div)
#The program:
until = 1000
for i in range(until):
if is_prime(i):
print i
當然……如果你喜歡遞歸函數,這個小代碼可以用字典來升級,以大大提高它的性能,並避免那個有趣的錯誤。 這是帶有 MEMORY 集成的簡單 1 級升級:
import datetime
def is_prime(n, div=2):
global primelist
if div> n/2.0: return True
if div < primelist[0]:
div = primelist[0]
for x in primelist:
if x ==0 or x==1: continue
if n % x == 0:
return False
if n% div == 0:
return False
else:
div+=1
return is_prime(n,div)
now = datetime.datetime.now()
print 'time and date:',now
until = 100000
primelist=[]
for i in range(until):
if is_prime(i):
primelist.insert(0,i)
print "There are", len(primelist),"prime numbers, until", until
print primelist[0:100], "..."
finish = datetime.datetime.now()
print "It took your computer", finish - now , " to calculate it"
這是結果,我打印了找到的最后 100 個素數。
時間和日期:2013-10-15 13:32:11.674448
有 9594 個素數,直到 100000
[99991, 99989, 99971, 99961, 99929, 99923, 99907, 99901, 99881, 99877, 99871, 99859, 99839, 99833, 99829, 99823, 99817, 99809, 99793, 99787, 99767, 99761, 99733, 99721, 99719 , 99713, 99709, 99707, 99689, 99679, 99667, 99661, 99643, 99623, 99611, 99607, 99581, 99577, 99571, 99563, 99559, 99551, 99529, 99527, 99523, 99497, 99487, 99469, 99439, 99431 , 99409, 99401, 99397, 99391, 99377, 99371, 99367, 99349, 99347, 99317, 99289, 99277, 99259, 99257, 99251, 99241, 99233, 99223, 99191, 99181, 99173, 99149, 99139, 99137, 99133 , 99131, 99119, 99109, 99103, 99089, 99083, 99079, 99053, 99041, 99023, 99017, 99013, 98999, 98993, 98981, 98963, 98953, 98947, 98939, 98929, 98927, 98911, 98909, 98899, 98897 ] ...
你的電腦用了 0:00:40.871083 來計算它
所以我的 i7 筆記本電腦花了 40 秒來計算它。 :)
# computes first n prime numbers
def primes(n=1):
from math import sqrt
count = 1
plist = [2]
c = 3
if n <= 0 :
return "Error : integer n not >= 0"
while (count <= n - 1): # n - 1 since 2 is already in plist
pivot = int(sqrt(c))
for i in plist:
if i > pivot : # check for primae factors 'till sqrt c
count+= 1
plist.append(c)
break
elif c % i == 0 :
break # not prime, no need to iterate anymore
else :
continue
c += 2 # skipping even numbers
return plist
您過早地終止循環。 在你測試了 for 循環體中的所有可能性並且沒有中斷之后,這個數字就是素數。 由於一個不是素數,你必須從 2 開始:
for num in xrange(2, 101):
for i in range(2,num):
if not num % i:
break
else:
print num
在更快的解決方案中,您只嘗試除以小於或等於您正在測試的數字的根的素數。 這可以通過記住你已經找到的所有素數來實現。 此外,您只需測試奇數(2 除外)。 您可以將生成的算法放入生成器中,以便將其用於將素數存儲在容器中或簡單地將它們打印出來:
def primes(limit):
if limit > 1:
primes_found = [(2, 4)]
yield 2
for n in xrange(3, limit + 1, 2):
for p, ps in primes_found:
if ps > n:
primes_found.append((n, n * n))
yield n
break
else:
if not n % p:
break
for i in primes(101):
print i
如您所見,無需計算平方根,存儲每個素數的平方並將每個除數與該數字進行比較會更快。
這個怎么樣? 閱讀我使用的所有建議:
prime=[2]+[num for num in xrange(3,m+1,2) if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1))]
質數高達 1000000
root@nfs:/pywork# time python prime.py
78498
真正的 0m6.600s
用戶 0m6.532s
系統 0m0.036s
除了已接受的答案之外,還可以通過使用列表來存儲素數並在生成后打印它們來實現進一步的優化。
import math
Primes_Upto = 101
Primes = [2]
for num in range(3,Primes_Upto,2):
if all(num%i!=0 for i in Primes):
Primes.append(num)
for i in Primes:
print i
這是初學者獲取素數的最簡單邏輯:
p=[]
for n in range(2,50):
for k in range(2,50):
if n%k ==0 and n !=k:
break
else:
for t in p:
if n%t ==0:
break
else:
p.append(n)
print p
n = int(input())
is_prime = lambda n: all( n%i != 0 for i in range(2, int(n**.5)+1) )
def Prime_series(n):
for i in range(2,n):
if is_prime(i) == True:
print(i,end = " ")
else:
pass
Prime_series(n)
這是使用 lambda 函數的簡化答案。
def function(number):
for j in range(2, number+1):
if all(j % i != 0 for i in range(2, j)):
print(j)
function(13)
使用 python 打印 n 個素數:
num = input('get the value:')
for i in range(2,num+1):
count = 0
for j in range(2,i):
if i%j != 0:
count += 1
if count == i-2:
print i,
def prime_number(a):
yes=[]
for i in range (2,100):
if (i==2 or i==3 or i==5 or i==7) or (i%2!=0 and i%3!=0 and i%5!=0 and i%7!=0 and i%(i**(float(0.5)))!=0):
yes=yes+[i]
print (yes)
min=int(input("min:"))
max=int(input("max:"))
for num in range(min,max):
for x in range(2,num):
if(num%x==0 and num!=1):
break
else:
print(num,"is prime")
break
這是我編寫的一個示例程序,用於檢查一個數字是否為素數。
def is_prime(x):
y=0
if x<=1:
return False
elif x == 2:
return True
elif x%2==0:
return False
else:
root = int(x**.5)+2
for i in xrange (2,root):
if x%i==0:
return False
y=1
if y==0:
return True
n = int(raw_input('Enter the integer range to find prime no :'))
p = 2
while p<n:
i = p
cnt = 0
while i>1:
if p%i == 0:
cnt+=1
i-=1
if cnt == 1:
print "%s is Prime Number"%p
else:
print "%s is Not Prime Number"%p
p+=1
使用過濾功能。
l=range(1,101)
for i in range(2,10): # for i in range(x,y), here y should be around or <= sqrt(101)
l = filter(lambda x: x==i or x%i, l)
print l
for num in range(1,101):
prime = True
for i in range(2,num/2):
if (num%i==0):
prime = False
if prime:
print num
添加我自己的版本,只是為了展示一些 itertools 技巧 v2.7:
import itertools
def Primes():
primes = []
a = 2
while True:
if all(itertools.imap(lambda p : a % p, primes)):
yield a
primes.append(a)
a += 1
# Print the first 100 primes
for _, p in itertools.izip(xrange(100), Primes()):
print p
f=0
sum=0
for i in range(1,101):
for j in range(1,i+1):
if(i%j==0):
f=f+1
if(f==2):
sum=sum+i
print i
f=0
print sum
省略素數的最快和最佳實現:
def PrimeRanges2(a, b):
arr = range(a, b+1)
up = int(math.sqrt(b)) + 1
for d in range(2, up):
arr = omit_multi(arr, d)
這是一種不同的方法,可以用空間換取更快的搜索時間。 這可能是最快的。
import math
def primes(n):
if n < 2:
return []
numbers = [0]*(n+1)
primes = [2]
# Mark all odd numbers as maybe prime, leave evens marked composite.
for i in xrange(3, n+1, 2):
numbers[i] = 1
sqn = int(math.sqrt(n))
# Starting with 3, look at each odd number.
for i in xrange(3, len(numbers), 2):
# Skip if composite.
if numbers[i] == 0:
continue
# Number is prime. Would have been marked as composite if there were
# any smaller prime factors already examined.
primes.append(i)
if i > sqn:
# All remaining odd numbers not marked composite must be prime.
primes.extend([i for i in xrange(i+2, len(numbers), 2)
if numbers[i]])
break
# Mark all multiples of the prime as composite. Check odd multiples.
for r in xrange(i*i, len(numbers), i*2):
numbers[r] = 0
return primes
n = 1000000
p = primes(n)
print "Found", len(p), "primes <=", n
我受到 Igor 的啟發,制作了一個創建列表的代碼塊:
def prime_number():
for num in range(2, 101):
prime = True
for i in range(2, num):
if (num % i == 0):
prime = False
if prime and num not in num_list:
num_list.append(num)
else:
pass
return num_list
num_list = []
prime_number()
print(num_list)
a=int(input('enter the lower no.'))
b=int(input('enter the higher no.'))
print("Prime numbers between",a,"and",b,"are:")
for num in range(a,b):
if num>1:
for i in range(2,num):
if (num%i)==0:
break
else:
print(num)
def fac(n):
res = []
for i in range(1,n+1):
if n%i == 0:
res.append(i)
def prime(n):
return(fac(n) == [1,n])
def prime_list(n):
pri_list = []
for i in range(1,n+1):
if prime(i)
pri_list.append(i)
return(pri_list)
for i in range(1, 100):
for j in range(2, i):
if i % j == 0:
break
else:
print(i)
作為一個行理解列表解決方案:
>>> [num for num in range(2, 101) if all(num % i != 0 for i in range(2, num))]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
其中101
表示列表的2
到100
之間的最大范圍值
1
只能除以一個數,即1
本身,因此根據這個定義,1
不是素數。 主數必須只有兩個正因數1
和itself
。
num= int(input("Enter the numbner"))
isDivisible= False
int=2
while i<num:
if num%i==0
isDivisible True
print("The number {} is divisible by {}.".format(num,i))
i +=1
if isDivisible:
print("The number {} is not prime.".format(num))
else:
print("The number {} is a prime number.".format(num))
min = int(input("輸入下限:")) max = int(input("輸入上限:"))
print("",min,"和",max,"之間的素數是:"
for num in range(min,max + 1): if num > 1: for i in range(2,num): if (num % i) == 0: break else: print(num)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.