Python和Sieve of Eratosthenes的200万以下素数总和,如何更快更有效地完成这项工作?

时间:2017-04-15 00:10:31

标签: python algorithm primes

这可以在~0.7s(2.2GHz i7四核)中完成,但我知道它可以更快。我认为学习如何提高速度可以教会我很多关于Python的知识。我如何加快速度?如何提高内存效率? (不使用多处理,仍使用eratosthenes筛)

from math import sqrt
import time

def sum_range(n):
    A = [1 if i > 1 else 0 for i in xrange(n+1)]
    for i, p in enumerate(A):
        if A[i] and i <= int(sqrt(n)):
            for j in xrange(i+i, n+1, i):
                A[j] = 0
    sum = 0
    for i, p in enumerate(A):
        if A[i]:
            sum += i
    return sum

if __name__ == '__main__':
    t0 = time.time()
    sum = sum_range(1000*1000*2)
    t1 = time.time()
    print "The sum is {} and it took {} seconds to do this".format(sum, t1-t0)

为了记录,这不是任何形式的作业问题。只是为了好奇。

1 个答案:

答案 0 :(得分:0)

在sqrt(2 * 10 ^ 6)之下只有223个素数。我是怎么发现的?去了wolframalpha并输入了#sq;数量低于sqrt(2e6)&#34;的素数。对不起,这是Java,但也应该适用于Python。

long sum = 2; // treat 2 separately
int len = (int) Math.sqrt(2000000) + 1, count = 0;
boolean[] sieve = new boolean[len];
int[] primes = new int[222]; // without 2
// do sieve only with the odd numbers and up to the root
for (int i = 3; i < len; i += 2) {
    if (!sieve[i]) {
        sum += i;
        primes[count++] = i;
        for (int j = 3 * i; j < len; j += 2 * i) // again only odd numbers
            sieve[j] = true;
    }
}
outer:
for (int i = len % 2 == 0 ? len + 1 : len; i < 2000000; i += 2) {
    for (int j = 0; j < primes.length && primes[j] * primes[j] <= i; j++)
        if (i % primes[j] == 0)
            continue outer;
    sum += i;
}

为了进一步改进,您还可以跳过所有可分为3的数字(每三个奇数可以被3分割。)