2012-08-01 125 views
2

我想不通爲什麼這個輸出出來爲:Python生成器返回停止迭代?

> File "<pyshell#177>", line 6, in func 
>  list.append(next(PrimeGen)) 
> StopIteration 

當它使這麼多的意義在我的頭上!無論如何,基本上我試圖使用一個ifprime函數和一個生成器來收集列表中的素數。

這決定了如果素數和返回值,否則什麼都不是。

def prime(x): 
    if (2**(x-1))%x ==1: 
     return x 

這使得應該返回全質數列表達X發電機,而是給出了上述錯誤。我開始用2裏面的名單,因爲上述功能的黃金(X)不考慮2作爲主要(所以範圍將在3日開始)

def func(x): 
    count=0 
    list=[2] 
    PrimeGen = (prime(X) for X in range(3,x+1)) 
    while count<99: 
     list.append(next(PrimeGen)) 
     count+=1 
    print list 

任何人可以解釋爲什麼它不」工作? 提前謝謝! V.

+0

相關:[列出Python中N以下所有素數的最快方法](http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python) – jfs 2012-08-01 19:47:11

回答

3

請注意,您的首要測試

def prime(x): 
    if (2**(x-1))%x ==1: 
     return x 

是錯誤的,聲明如341 = 11*312047 = 23*89素數。

另外,對於較大x,產生非常大的中間值,更有效的是

pow(2,x-1,x) 

降低所述中間值。

適度有效的實現更強的素性檢查:

# The primes below 200 used as bases for the strong Fermat test, 
# prime bases have more discriminatory power than composite bases, 
# therefore we use prime bases first 
bases = [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, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199] 

# The strong Fermat test for base b, where n is odd and large, 
# n - 1 = m * 2^s with odd m 
# the strong test checks whether b**m % n == 1 or 
# b**(2**j) % n == n-1 for a 0 <= j < s 
# If the test returns False, n is definitely composite, otherwise probably prime 
def strongFermat(b,n,m,s): 
    a = pow(b,m,n) 
    if a == 1: 
     return True 
    n1 = n-1 
    for i in xrange(s): 
     if a == n1: 
      return True 
     a = (a*a) % n 
    return False 

# Multiple strong Fermat tests, by default use 10 bases 
# The probability that a composite passes is less than 0.25**iters 
def sppTest(n, iters = 10): 
    # Assumes n > 1 and with no prime divisors < 200 
    m = n-1 
    s = 0 
    while (m & 1) == 0: 
     m >>= 1 
     s += 1 
    pbases = iters if iters < 47 else 46 
    for i in xrange(pbases): 
     if not strongFermat(bases[i],n,m,s): 
      return False 
    if pbases < iters: 
     for i in xrange(iters-pbases): 
      if not strongFermat(211 + 2*i,n,m,s): 
       return False 
    return True 

# Trial division to weed out most composites fast 
def trialDivisionPrime(n): 
    if n < 2: 
     return 0  # Not a prime 
    if n < 4: 
     return 2  # definitely prime 
    if n % 2 == 0 or n % 3 == 0: 
     return 0  # definitely composite 
    for d in xrange(5, 200, 6): 
     if d*d > n: 
      return 2 # definitely prime 
     if n % d == 0 or n % (d+2) == 0: 
      return 0 # composite 
    return 1   # not yet decided 

# The prime test, first do trial division by numbers < 200, 
# if that doesn't decide the matter, use some strong Fermat tests 
# using 20 tests is the paranoid setting for largish numbers, 
# for numbers in 64-bit range, ten or fewer suffice 
def prime(n): 
    td = trialDivisionPrime(n) 
    return td > 1 or (td == 1 and sppTest(n,20)) 

# just check a couple of larger numbers 
for c in xrange(100000): 
    if prime(c + 10**25): 
     print c 
+0

哦,這很奇怪,我用Fermat的小定理,我只是假設它是防彈的......還是我把它翻譯錯了python?感謝更高效的翻譯,雖然 – 2012-08-01 19:52:29

+3

翻譯是正確的,但該定理只列出了作爲素數的必要條件。具有測試性質的複合整數被稱爲「費馬假病毒」。還有更多的快速概率主要測試,但已知的最終主要測試仍然明顯較慢。你可以通過使用更多的基數來獲得更高的正確率,並且我建議切換到強大的費馬測試,這更強大,更簡單。 – 2012-08-01 19:58:00

5

生成的值不足99個。使用itertools.islice()而不是循環。

1

這是更好一點(這似乎有點傻有你的「黃金」函數返回無論是數量,如果是黃金或None否則,雖然它會在地方稍作修改的版本低於因如何bool(None) == False實際上只是正常工作),並不會導致你得到StopIteration

def isprime(x): 
    return (2**(x-1))%x==1 

def func(x): 
    list=[2] 
    list.extend(X for X in range(3,x+1) if isprime(X)) 
    print list 

但由什麼丹尼爾·菲捨爾說,你去無論如何,r總理函數是不正確的。