素数的生成器函数

时间:2014-09-07 03:44:03

标签: python generator primes

我正在尝试编写用于打印素数的生成器函数,如下所示

 def getPrimes(n):
    prime=True
    i=2
    while(i<n):
        for a in range(2,i):
            if(i%a==0):
                prime=False
                break
        if(prime):    
            yield i

然而,我没有得到预期的结果 p = getPrimes(100)应该给我一个生成器函数,它将从2到100迭代素数,但我得到的结果是[2,3]。我做错了什么?

5 个答案:

答案 0 :(得分:9)

Eratosthenes的筛选:最有效的素数生成器算法

取自此处:

Simple Prime Generator in Python - Eli Bendersky的回答。

enter image description here

它标记了235711的所有倍数。其余的都是素数。

def genprimes(limit): # derived from 
                      # Code by David Eppstein, UC Irvine, 28 Feb 2002
    D = {}            # http://code.activestate.com/recipes/117119/
    q = 2

    while q <= limit:
        if q not in D:
            yield q
            D[q * q] = [q]
        else:
            for p in D[q]:
                D.setdefault(p + q, []).append(p)
            del D[q]
        q += 1

p = genprimes(100)
prms = [i for i in p]

print prms

输出:

[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]

答案 1 :(得分:3)

您需要将prime重置为True作为while块内的第一个语句,而不是之前的语句。事实上,一旦你点击一个复合数字,prime将永远不再成为现实,所以你永远不会再产生任何数字。

答案 2 :(得分:2)

您有几个错误,请参阅评论:

def getPrimes(n):
    i = 2
    while i < n :
        prime = True # reset the `prime` variable before the inner loop
        for a in xrange(2, i):
            if i%a == 0:
                prime = False
                break
        if prime:    
            yield i
        i += 1 # don't forget to advance `i`

现在为了更好地实现正确处理边缘情况,执行少量迭代并生成小于n参数值的素数序列:

def getPrimes(n):
    if n <= 2:
        raise StopIteration
    yield 2
    for i in xrange(3, n, 2):
        for x in xrange(3, int(i**0.5)+2, 2):
            if not i % x:
                break
        else:
            yield i

无论哪种方式,代码都按预期工作:

[x for x in getPrimes(20)]
=> [2, 3, 5, 7, 11, 13, 17, 19]

答案 3 :(得分:1)

def isprime(n):
    for i in range(2 ,int((n**0.5))+1):
        if n % i == 0:
            return False
    return True

def getPrimes(n):
    yield 2
    i = 1
    while i <= n-2:
        i += 2
        if isprime(i):
            yield i

答案 4 :(得分:1)

作为Istvan Chung answered,您的问题来自于您无法重置prime标志。但是,我建议另一种解决方案,而不是直接解决这个问题。

在没有点击break的情况下,不是使用标志变量来检测你何时在整个循环中完成它,而是在循环后使用else块:

def getPrimes(n):
    i = 2
    while i < n :
        for a in range(2, i):
            if i % a == 0:
                break
        else:    
            yield i

如果循环完成,else块将运行,而不是由break语句提前停止。

你可以通过仅测试素数除数而不是所有小于i的整数来进一步改善这一点。这是一种使用递归的方法(另一种方法是保留先前计算的素数列表,但如果n非常大,则可能需要大量存储空间):

def getPrimes(n):
    yield 2
    i = 3
    while i < n:
        for a in getPrimes(int(math.sqrt(i))+1):
            if i % a == 0:
                break
        else:
            yield i
        i += 2