如何在 python 中对所有质数生成无限生成器?

How to make an infinite generator in python to all prime numbers?

我试图在 python 中制作这个无限生成器:

import math
def all_primes():
    count = 2
    while True:
        flag = True
        for x in range(2, int(math.sqrt(count) + 1)):
            if count % x == 0: 
                flag = False
        
        if flag:
            yield count
        else:
            count += 1
            
for i in all_primes():
    print(i)

但在输出中它总是给我 2。这是为什么?

您在找到质数后不会增加计数,因此您总是返回相同的值 (3)。

随着您的前进,您的素数生成器将在每个素数之间花费越来越长的时间。

这是一个效率更高的无限素数生成器。它的灵感来自 Eratosthenes 的筛子,但使用字典仅在达到 non-prime 数字时传播倍数,并将素数倍数移动到下一个尚未标记为 non-prime 的倍数:

def genPrimes():
    yield 2                      # get the first prime out of the way
    skips      = dict()          # multiples to skip {Multiple:2xPrime}
    multiples  = ((p*p,2*p) for p in genPrimes()) # multiples of primes
    skipMark,_ = next(multiples)                  # skipping coverage
    N = 1                        # prime candidate (odd numbers)
    while True:
       N += 2                        # next prime candidate
       if N >= skipMark:                     # extend skips coverage
           skipMark,stride = next(multiples) # 1st multiple and stride
           skips[skipMark] = stride          
       if N in skips:                # not a prime (multiple of a prime)   
           stride   = skips.pop(N)   # get prime multiple steps
           multiple = N + stride     # advance skip to next multiple
           while multiple in skips:
               multiple += stride    # not already skipped
           skips[multiple] = stride
       else:                         # N is prime
           yield N                   # return it 

输出:

for p in genPrimes(): print(p)
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
...

skips 字典包含每个√P(其中 P 是到目前为止找到的素数的数量)大约一个条目并且不需要 pre-allocating 内存。这种方法用 space 来换取时间上的收益。

您的代码总是产生“3”的原因是 'flag' 始终为真。在 for 循环中使用 int(math.sqrt(count)+1) 进行数学运算使得循环仅从 2 -> 2 开始。所以唯一检查的是 if 3 % 2 == 0 这是永远不会是真的。因此标志始终为假,计数永远不会增加。

那是因为 for 循环从不迭代。如果 count=3 那么 int(math.sqrt(count) + 1) 就是 return 2,所以你的 for 循环的范围是 (2,2),因此它永远不会迭代,标志值也不会改变,因此计数值始终相同。