使用Python项目Euler#10,Numpy sum总和不正确

时间:2014-03-13 17:24:58

标签: python primes

Project Euler #10

我知道这个问题已经被问到,但是我很难找到为什么我得到了错误的答案,其他关于这个的帖子对我没有帮助。代码是找到低于2,000,000的素数之和。

import math
import numpy as np

def sum_primes(limit):      
    potential = 2
    primes = [potential]
    potential += 1
    primes.append(potential)

    while potential < limit:
        potential+=2
        test = True
        sqrt_potential = math.sqrt(potential)
        for a in primes:
            if a > sqrt_potential:
                break
            if potential%a == 0:
                test = False
                break
        if test and potential <= limit:
            primes.append(potential)

    print np.sum(primes)
    return

看来我正在击中所有素数,但由于某种原因,总和还没有正确出现。有人在这看到问题吗?

以下是我得到的一些输出:

>>> sum_primes(20000)
21171191
>>> sum_primes(200000)
1709600813
>>> sum_primes(2000000)
1179908154

2 个答案:

答案 0 :(得分:2)

在脚本的初始化部分,设置potential = 3。然后while循环中的第一个语句将potential增加到5.您永远不会将3视为潜在素数。通过在脚本的初始化部分设置potential -= 1来修复它。

更好的算法使用了Eratosthenes的Sieve:

def sumPrimes(n):
    b, p, sum = [True] * (n+1), 2, 0
    for p in xrange(2, n+1):
        if b[p]:
            sum += p
            for i in xrange(p, n+1, p):
                b[i] = False
    return sum

如果您要在Project Euler中执行素数问题,您可能需要在我的博客上阅读Programming with Prime Numbers

答案 1 :(得分:2)

我给出了一个相当天真的实现,最后一次迭代需要一段时间才能返回结果。

def return_primes(upto=100):
    primes = []
    for i in range(2, upto+1):
        if not any(not i % p for p in primes):
            primes.append(i)
    return primes

用法:

>>> sum(return_primes(upto=20000))
21171191
>>> sum(return_primes(upto=200000))
1709600813
>>> sum(return_primes(upto=2000000))
142913828922

这是使用Sieve of Eratosthenes的另一个实现:

def return_primes(upto=100):
    primes = []
    sieve = set()
    for i in range(2, upto+1):
        if i not in sieve:
            primes.append(i)
            sieve.update(range(i, upto+1, i))
    return primes

这比更多更快,在大约一两秒内运行,而上述时间则为几分钟:

>>> sum(return_primes(200000))
1709600813
>>> sum(return_primes(2000000))
142913828922

要尝试使用此信息更好地诊断您的问题,我们会看到

>>> 142913828922 % 2**32
1179908154

哪位(谢谢Will Ness)让人得出结论,你用32位整数求和。如果我们将您的代码更改为以下内容:

import math
import numpy as np

def sum_primes(limit):      
    potential = 2
    primes = [potential]
    potential += 1
    primes.append(potential)
    while potential < limit:
        potential+=2
        test = True
        sqrt_potential = math.sqrt(potential)
        for a in primes:
            if a > sqrt_potential:
                break
            if potential%a == 0:
                test = False
                break
        if test and potential <= limit:
            primes.append(potential)
    print np.sum(primes, dtype=np.int64)
    return

然后你应该得到正确的输出。

如果我改用你的行为,我会复制你的行为:

    print np.sum(primes, dtype=np.int32)