素数计算器不产生输出(python)

时间:2017-04-30 12:25:18

标签: python python-3.x primes

我试图使用基本逻辑找到第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])

3 个答案:

答案 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。