我正在尝试以下方法来生成素数:
primes = [2]
candidate = 3
MILLION = 1000000
while candidate < MILLION:
if all(candidate % prime for prime in primes if prime**2 <= candidate):
primes.append(candidate)
candidate += 2
然而,这比我以前的代码慢得多,我之前没有使用all
函数,并且我自己进行了如下检查:
primes = [2]
candidate = 3
MILLION = 1000000
while candidate < MILLION:
can_be_prime = True
for p in primes:
if p**2 > candidate:
break
elif candidate % p == 0:
can_be_prime = False
break
if can_be_prime:
primes.append(candidate)
candidate += 2
当第二个在10秒内结束时,第一个需要永远完成。有人可以帮我理解为什么第一个100000数字后第一个开始输出的速度如此之慢?
答案 0 :(得分:4)
虽然您想要使用该生成器表达式缩短代码并且any
是好的,但它们并不等同。特别是,在较长的解决方案中,只要找到p ** 2 > candidate
为真的素数,就会迭代(已排序的)素数列表并中断迭代。
但是,在您的生成器表达式中,您尝试使用x for p in primes if p ** 2 <= candidate
进行此检查。遗憾的是,不相同。即使该检查失败,生成器仍将继续迭代剩余的素数,对每个素数执行p ** 2
,在外部的每次迭代上执行while
循环。
如果你的写法有点不同,你可以验证这是问题所在:
def getPrimes (candidate):
for p in primes:
if p ** 2 > candidate:
break
yield p
while candidate < MILLION:
if all(candidate % prime for prime in getPrimes(candidate)):
primes.append(candidate)
candidate += 2
所以现在,我们在较长版本中使用相同的想法,并在我们点击primes
为真的素数时立即中止p ** 2 > candidate
上的迭代。这样,我们就可以从更长的解决方案中获得速度。
答案 1 :(得分:0)
我们实际上可以使用6n +/- 1
规则来生成素数。
例如,如果要为给定数字生成素数:
def primes(N):
if N == 2:
primes = [2]
elif N >= 3:
primes = [2, 3]
else:
return None
for i in range(6, N):
if i % 6 == 0:
left = i - 1
right = i + 1
if all(left % p != 0 for p in primes):
primes.append(left)
if all(right % p != 0 for p in primes):
primes.append(right)
return primes