如何在 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),因此它永远不会迭代,标志值也不会改变,因此计数值始终相同。
我试图在 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),因此它永远不会迭代,标志值也不会改变,因此计数值始终相同。