我想优化这段代码,以便缩短完成此任务的时间(我确实希望继续打印所有素数):
(获得第10001个素数)
counter = 10001
target_num = 1 #because if we add 1 to it the first time, it will become 2
input('This may take a while, press Enter to continue; you can stop the program any time by pressing CTRL + C.')
while counter <= 10001 and counter > 0:
target_num = target_num + 1
for x in range(1, target_num + 1):
if target_num % x == 0:
if x == 1:
pass
elif x != target_num:
break
elif x == target_num:
counter = counter - 1
print (target_num) #prints prime number so user knows if program is actually crunching numbers
print ('10001st prime number is: ' + str(target_num))
答案 0 :(得分:3)
我计算了你的代码。这需要多长时间:
Over 72 seconds (%timeit died, sorry!)
明显的问题是你将循环从1运行到target_num
以找到素数。那个不是是必要的。
可以看到here的证据。
这是一个运行到平方根的版本。您也可以删除那些多余的if
。
def foo():
counter = 10001
target_num = 1 #because if we add 1 to it the first time, it will become 2
while counter <= 10001 and counter > 0:
target_num = target_num + 1
for x in range(2, int(target_num ** 0.5) + 1 ):
if target_num % x == 0:
if x != target_num:
break
else:
counter -= 1
print ('10001st prime number is: ' + str(target_num))
定时:
1 loop, best of 3: 442 ms per loop
进一步加速可以通过步进范围2来实现,因此您可以跳过对偶数的检查:
def foo():
counter = 10000
target_num = 1
while counter <= 10001 and counter > 0:
target_num = target_num + 2
...
定时:
1 loop, best of 3: 378 ms per loop
脚注: 这个答案解释了您当前方法的不足之处。但是,对于一种全新的方法,请查看Sieve of Eratosthenes - Finding Primes Python或@ AChampion的答案。
答案 1 :(得分:1)
快速素数生成器有很多资源
例如,您可以安装提供的primesieve
:
In []:
import primesieve
primesieve.nth_prime(10001)
Out[]:
104743
In []:
%timeit primesieve.nth_prime(10001)
Out[]:
28.3 µs ± 549 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
简单筛子的原生python实现:
In []:
import itertools as it
def primes():
yield 2
sieve = {}
for n in it.count(3, 2):
if n not in sieve:
sieve[n*n] = 2*n
yield n
continue
a = sieve.pop(n)
x = n + a
while x in sieve:
x += a
sieve[x] = a
def nth_prime(n):
return next(it.islice(primes(), n-1, None))
nth_prime(10001)
Out[]:
104743
In []:
%timeit nth_prime(10001)
Out[]:
26.3 ms ± 629 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)