素数代码的优化

时间:2011-11-05 10:02:41

标签: python primes

这是我在python中的代码,用于计算小于给定数字的素数之和 我还能做些什么来优化它?

import math
primes = [2,]                      #primes store the prime numbers



for i in xrange(3,20000,2):                    #i is the test number
    x = math.sqrt(i)
    isprime = True
    for j in primes:               #j is the devider. only primes are used as deviders
        if j <= x:
            if i%j == 0:
                    isprime = False
                    break


    if isprime:
        primes.append(i,)


print sum (primes,)

5 个答案:

答案 0 :(得分:5)

你可以使用一种名为Sieve of Eratosthenes的不同算法,它会更快但需要更多内存。保留一组标志,表示每个数字是否为素数,并且对于每个新的素数集,它对于该素数的所有倍数都为零。

N = 10000

# initialize an array of flags
is_prime = [1 for num in xrange(N)]
is_prime[0] = 0 # this is because indexing starts at zero
is_prime[1] = 0 # one is not a prime, but don't mark all of its multiples!

def set_prime(num):
    "num is a prime; set all of its multiples in is_prime to zero"
    for x in xrange(num*2, N, num):
        is_prime[x] = 0

# iterate over all integers up to N and update the is_prime array accordingly
for num in xrange(N):
    if is_prime[num] == 1:
        set_prime(num)

primes = [num for num in xrange(N) if is_prime[num]]

如果您使用有效的位数组,例如在this example中(在页面上向下滚动,您将找到一个Sieve of Eratosthenes示例),您实际上可以为相当大的N执行此操作。

答案 1 :(得分:4)

您可以优化的另一件事是将sqrt计算移到内部循环之外。毕竟,i通过它保持不变,因此无需每次都重新计算sqrt(i)

答案 2 :(得分:3)

primes = primes + (i,)非常昂贵。它复制循环每次传递的每个元素,将优雅的动态编程解决方案转换为O(N 2 )算法。改为使用列表:

primes = [2]
...
    primes.append(i)

此外,在传递sqrt(i)之后提前退出循环。并且,由于您保证在运行素数列表的末尾之前传递sqrt(i),因此就地更新列表而不是存储isprime以供以后使用:

...
if j > math.sqrt(i):
    primes.append(i)
    break
if i%j == 0:
    break
...

最后,尽管这与性能无关,但使用范围而不是while时更加Pythonic:

for i in range(3, 10000, 2):
    ...

答案 3 :(得分:1)

不使用任何导入的另一个代码:

#This will check n, if it is prime, it will return n, if not, it will return 0
def get_primes(n):
    if n < 2:
        return 0
    i = 2
    while True:
        if i * i > n:
            return n
        if n % i == 0:
            return 0
        i += 1

#this will sum up every prime number up to n
def sum_primes(n):
    if n < 2:
        return 0
    i, s = 2, 0
    while i < n:
        s += get_primes(i)
        i += 1
    return s

n = 1000000
print sum_primes(n)

答案 4 :(得分:0)

编辑:在受到影响时删除了一些愚蠢

所有用于查找素数的强力型算法,无论效率如何,都会随着上限的增加而变得非常昂贵。测试素数的启发式方法实际上可以节省大量计算。已建立divisibility rules可以“一目了然”消除大多数非素数。