我试图使用基本逻辑找到第10001个素数: 1)确定一个数字是否为素数 2)如果是素数,则将其添加到列表中 3)在列表中打印第10001个术语
这是我的代码:
primelist=[]
import math
i=2
while True:
for x in range(2, int(math.sqrt(i))):
if i % x == 0:
continue
else:
primelist.append(i)
if len(primelist)== 10001:
break
print(primelist[-1])
逻辑或代码是根本错误还是低效?
我可以做些什么来改善/使其发挥作用?
修改
我已增加i(i+=1
)并使用all()
检查所有内容是否不可分割,以回应评论
primelist=[2]
import math
i=3
while True:
for x in range(2, int(i**(1/2))):
if all(i%x!=0 for x in range(2, int(math.sqrt(i)))):
primelist.append(i)
i+=1
if len(primelist)== 10001:
break
print(primelist[-1])
答案 0 :(得分:1)
如果您想继续使用算法,这个应该可以使用:
import math
def is_prime(n):
for x in range(2, int(math.sqrt(n)) + 1):
if n % x == 0:
return False
return True
primelist = []
i = 2
while True:
if is_prime(i) is True:
primelist.append(i)
i += 1
if len(primelist) == 10001:
break
print(primelist[-1])
答案 1 :(得分:1)
保持算法/代码结构相同(未完成优化),因此我们可以轻松共享多个语言点,请参阅内联注释:
primelist=[]
import math
i=2
while True:
#changed to sqrt + 1, the second parameter of range is not inclusive,
#by adding 1, we make sure sqrt itself is included
for x in range(2, int(math.sqrt(i) + 1)):
if i % x == 0:
#you want break not continue, continue will try
#next possible factor, since you already figured out that this
#is not a prime, no need to keep trying
#continue
break
#a for/else block, many python users never encountered this python
#syntax. The else block is only triggered, if the for loop is naturally
#completed without running into the break statement
else:
#a little debugging, to visually confirm we generated all primes
print("adding {}".format(i))
primelist.append(i)
if len(primelist)== 11:
break
#advance to the next number, this is important,
#otherwise i will always be 2
i += 1
print(primelist[-1])
如果您想优化算法,请在线搜索“主筛”。
答案 2 :(得分:0)
这里的代码版本速度更快,并且没有使用太多内存。我们真的不需要建立我们找到的素数列表。我们不会使用该列表中的数字来查找更多素数,而我们实际上只对其长度感兴趣。因此,我们不仅仅是建立一个列表,而是只记录我们找到的素数。
# Include 2 in the count
count = 1
i = 3
while True:
if all(i % x for x in range(3, int(i ** 0.5) + 1, 2)):
count += 1
if count == 10001:
break
i += 2
print(i)
FWIW,这是一个使用筛分的更快的解决方案。我们使用素数定理估计所需的筛子尺寸。 Wikipedia为p(n)提供了这些边界,这是第n个素数,对于n> = 6有效:
log(n)+ log(log(n)) - 1< p(n)/ n< log(n)+ log(log(n))
我们使用上限作为筛子中的最高数量。对于n < 6我们使用硬编码列表。
为了节省空间,这个筛只能保留奇数,所以我们将p(1)== 2的情况视为特例。
#!/usr/bin/env python3
''' Use a sieve of Eratosthenes to find nth prime
Written by PM 2Ring 2017.05.01
Sieve code derived from primes1 by Robert William Hanks
See http://stackoverflow.com/a/3035188/4014959
'''
from math import log
from sys import argv
def main():
num = int(argv[1]) if len(argv) > 1 else 10001
if num == 1:
# Handle 2 as a special case
print(1, 2)
return
elif num < 6:
# Use a pre-built table for (3, 5, 7, 11)
primes = [1, 1, 1, 1, 0, 1]
else:
# Compute upper bound from Prime number theorem
x = log(num)
hi = int(num * (x + log(x)))
print('upper bound', hi)
# Create a boolean list of odd primes in range(hi)
primes = [True] * (hi//2)
for i in range(3, 1 + int(hi**0.5), 2):
if primes[i//2]:
primes[i*i//2::i] = [False] * ((hi - i*i - 1) // (2*i) + 1)
# Count the primes until we get the nth one
k = 0
for i, b in enumerate(primes):
if b:
k += 1
if k == num:
break
print(num, 2*i+1)
if __name__ == "__main__":
main()
此代码在运行Python 3.6.0的旧单核32位2GHz机器上在0.15秒内找到p(10001)= 104743。它在大约2.2秒内找到p(500000)= 7368787。