【问题标题】:Python Generator returning stop iteration?Python生成器返回停止迭代?
【发布时间】:2012-08-01 19:34:57
【问题描述】:

我不明白为什么这个输出是:

>  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 开头的列表,因为上面的函数 prime(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

谁能解释为什么它不起作用? 先感谢您! 五、

【问题讨论】:

标签: python generator primes


【解决方案1】:

生成的值少于 99 个。使用itertools.islice() 而不是循环。

【讨论】:

    【解决方案2】:

    请注意,您的主要测试

    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
    

    【讨论】:

    • 哦,这很奇怪,我使用了费马的小定理,我只是认为它是防弹的......还是我把它错误地翻译成 python?感谢您提供更高效的解决方案
    • 翻译是正确的,但该定理只陈述了质数的必要条件。具有测试属性的复合整数称为“费马伪素数”。有许多更快的概率素数测试,但已知的确定性素数测试仍然明显慢得多。使用更多的碱基可以获得更高的正确率,我建议切换到强 Fermat 测试,它更强大且几乎不复杂。
    【解决方案3】:

    这有点好(让你的“素数”函数返回素数或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
    

    但是按照 Daniel Fischer 的说法,你的主要函数无论如何都是不正确的。

    【讨论】:

      猜你喜欢
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-05
      • 1970-01-01
      • 2018-11-01
      相关资源
      最近更新 更多