[英]generator in Python generating prime numbers
我需要在Python中使用生成器生成素數。 這是我的代碼:
def genPrimes():
yield 2
x=2
while True:
x+=1
for p in genPrimes():
if (x%p)==0:
break
else:
yield x
我有一個RuntimeError:當我運行它時,在第二個prime.next()之后超出了最大遞歸深度。
生成素數的最快方法是使用篩子。 在這里,我們使用分段的Eratosthenes篩子按順序逐個生成素數,沒有最大值; ps
是小於當前最大值的篩選素數列表, qs
是當前段中相應ps
的最小倍數的偏移量。
def genPrimes():
def isPrime(n):
if n % 2 == 0: return n == 2
d = 3
while d * d <= n:
if n % d == 0: return False
d += 2
return True
def init(): # change to Sieve of Eratosthenes
ps, qs, sieve = [], [], [True] * 50000
p, m = 3, 0
while p * p <= 100000:
if isPrime(p):
ps.insert(0, p)
qs.insert(0, p + (p-1) / 2)
m += 1
p += 2
for i in xrange(m):
for j in xrange(qs[i], 50000, ps[i]):
sieve[j] = False
return m, ps, qs, sieve
def advance(m, ps, qs, sieve, bottom):
for i in xrange(50000): sieve[i] = True
for i in xrange(m):
qs[i] = (qs[i] - 50000) % ps[i]
p = ps[0] + 2
while p * p <= bottom + 100000:
if isPrime(p):
ps.insert(0, p)
qs.insert(0, (p*p - bottom - 1)/2)
m += 1
p += 2
for i in xrange(m):
for j in xrange(qs[i], 50000, ps[i]):
sieve[j] = False
return m, ps, qs, sieve
m, ps, qs, sieve = init()
bottom, i = 0, 1
yield 2
while True:
if i == 50000:
bottom = bottom + 100000
m, ps, qs, sieve = advance(m, ps, qs, sieve, bottom)
i = 0
elif sieve[i]:
yield bottom + i + i + 1
i += 1
else: i += 1
使用試驗除法的簡單isPrime
就足夠了,因為它將限於n的第四個根。 段大小2 * delta
任意設置為100000.該方法需要O(sqrt n )空間用於篩分素數加上篩子的恆定空間。
它是較慢的,但可以節省空間,以產生與車輪候選素數,並用測試素性候選人isPrime
基於強偽測試,以鹼基2,圖7和61; 這對2 ^ 32有效。
def genPrimes(): # valid to 2^32
def isPrime(n):
def isSpsp(n, a):
d, s = n-1, 0
while d % 2 == 0:
d /= 2; s += 1
t = pow(a,d,n)
if t == 1: return True
while s > 0:
if t == n-1: return True
t = (t*t) % n; s -= 1
return False
for p in [2, 7, 61]:
if n % p == 0: return n == p
if not isSpsp(n, p): return False
return True
w, wheel = 0, [1,2,2,4,2,4,2,4,6,2,6,4,2,4,\
6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,\
2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]
p = 2; yield p
while True:
p = p + wheel[w]
w = 4 if w == 51 else w + 1
if isPrime(p): yield p
如果你對使用素數編程感興趣,我謙虛地在我的博客上推薦這篇文章 。
genPrimes()
無條件地使用完全相同的參數調用自身。 這導致無限遞歸。
以下是使用(非遞歸)生成器執行此操作的一種方法:
def gen_primes():
n = 2
primes = set()
while True:
for p in primes:
if n % p == 0:
break
else:
primes.add(n)
yield n
n += 1
請注意,這是為了簡化和清晰而不是性能而優化的。
找到素數的好方法。 n
是停止搜索的上限。
def prime(i, primes):
for prime in primes:
if not (i == prime or i % prime):
return False
primes.add(i)
return i
def find_primes(n):
primes = set([2])
i, p = 2, 0
while True:
if prime(i, primes):
p += 1
if p == n:
return primes
i += 1
非常好! 當達到x
平方根時,你只是忘了停止從內部genPrimes()
獲取素數。 就這樣。
def genPrimes():
yield 2
x=2
while True:
x+=1
for p in genPrimes():
if p*p > x: #
yield x #
break #
if (x%p)==0:
break
# else:
# yield x
如果沒有它,你會從深層滑落,或者是什么表達。 當蛇吃自己的尾巴時,它必須停在中間。 如果它到達它的頭部,就沒有蛇了(好吧,這里的吃飯方向相反,但它仍然適用......)。
更簡潔一點:
import itertools
def check_prime(n, primes):
for p in primes:
if not n % p:
return False
return True
def prime_sieve():
primes = set()
for n in itertools.count(2):
if check_prime(n, primes):
primes.add(n)
yield n
你可以像這樣使用它:
g = prime_sieve()
g.next()
=> 2
g.next()
=> 3
g.next()
=> 5
g.next()
=> 7
g.next()
=> 11
這是一個快速而明確的命令式素數發生器,不使用篩子:
def gen_primes():
n = 2
primes = []
while True:
is_prime = True
for p in primes:
if p*p > n:
break
if n % p == 0:
is_prime = False
break
if is_prime:
primes.append(n)
yield n
n += 1
它幾乎與NPE的答案相同,但包括一個根測試,它顯着加速了大質數的產生。 結果是primes
列表的O(n)空間使用。
這是一個腳本,它生成從2到給定數字的素數列表
from math import sqrt
next = 2
n = int(raw_input())
y = [i for i in range(2, n+1)]
while y.index(next)+1 != len(y) and next < sqrt(n):
y = filter(lambda x: x%next !=0 or x==next, y)
next = y[y.index(next)+1]
print y
這只是Eratosthenes篩選的另一個實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.