Python 改进Euler#10的运行时间

Python 改进Euler#10的运行时间,python,performance,math,sieve-of-eratosthenes,Python,Performance,Math,Sieve Of Eratosthenes,所以我在攻克一个Euler问题,这个问题在小范围内看起来很简单,但一旦我把它提升到我应该做的数字,代码就会永远运行下去。问题是: 低于10的素数之和为2+3+5+7=17 求200万以下所有素数之和 我是用Python做的。我可以等几个小时让代码运行,但我更愿意找到一种更有效的方法。以下是我的Python代码: x = 1; total = 0; while x <= 2000000: y = 1; z = 0; while x >= y:

所以我在攻克一个Euler问题,这个问题在小范围内看起来很简单,但一旦我把它提升到我应该做的数字,代码就会永远运行下去。问题是:

低于10的素数之和为2+3+5+7=17

求200万以下所有素数之和

我是用Python做的。我可以等几个小时让代码运行,但我更愿意找到一种更有效的方法。以下是我的Python代码:

x = 1;
total = 0;

while x <= 2000000:
    y = 1;
    z = 0;
    
    while x >= y:    
        if x % y == 0:
            z += 1;   
        
        y += 1;
            
    if z == 2:
        total += x
    
    x += 1;
            
print total;
x=1;
总数=0;
当x=y时:
如果x%y==0:
z+=1;
y+=1;
如果z==2:
总数+=x
x+=1;
打印总数;

很明显,这个帐篷里的长杆首先在计算素数列表。对于这种人为的情况,你可以得到其他人的列表(比如,一个),练习一下,然后在几秒钟内把数字加起来


但在我看来,这是不道德的。在这种情况下,如SO回答中所述,尝试atkin筛。

如评论中所述,实施埃拉托斯烯筛将是一个更好的选择。它占用了
O(n)
额外的空间,在本例中,这是一个长度约为200万的数组。它也在
O(n)
中运行,这比在
O(n²)
中运行的实现要快得多

我最初是用JavaScript编写的,所以请容忍我的python:

max = 2000000    # we only need to check the first 2 million numbers
numbers = []
sum = 0

for i in range(2, max):    # 0 and 1 are not primes
    numbers.append(i)      # fill our blank list
for p in range(2, max):
    if numbers[p - 2] != -1:   # if p (our array stays at 2, not 0) is not -1
        # it is prime, so add it to our sum              
        sum += numbers[p - 2]
        # now, we need to mark every multiple of p as composite, starting at 2p
        c = 2 * p
        while c < max:
            # we'll mark composite numbers as -1
            numbers[c - 2] = -1
            # increment the count to 3p, 4p, 5p, ... np
            c += p

print(sum)
max=2000000#我们只需要检查前200万个数字
数字=[]
总和=0
对于范围(2,max)中的i:#0和1不是素数
数字。附加(i)#填写我们的空白列表
对于范围内的p(2,最大值):
如果数字[p-2]!=-1:#如果p(我们的数组保持在2,而不是0)不是-1
#它是素数,所以把它加到我们的和中
总和+=数字[p-2]
#现在,我们需要将p的每一个倍数标记为复合,从2p开始
c=2*p
当c

这里唯一令人困惑的部分可能是我为什么使用
数字[p-2]
。这是因为我跳过了0和1,这意味着2在索引0处。换句话说,所有的东西都被2个索引移到一边。

为了找到一个素数,而不是将所有的数字循环到素数,只需从2循环到数字的根,如果有匹配项,你知道它不是素数。这将使您的代码在
O(n*sqrt(n))
中运行,而不是
O(n^2)
您可能还需要研究更高效的素数生成算法,如、或