试图用Python编写Eratosthenes Sieve。这是正确的,我怎样才能让它更快?

时间:2012-12-14 13:55:01

标签: python python-2.7 sieve-of-eratosthenes

  

可能重复:
  Fastest way to list all primes below N in python

我已经很长时间没有编程了,我只是为了好玩而做这件事,而且我不太懂高级Python,但...... 我写了这篇文章,我想知道它是否真的是一个Eratosthenes Sieve程序,如果是,我怎么能让它更快。我真的不希望有人发布一个解决方案,但更多的是告诉我如何适应我的。

def eratSieve(n):
    all = []
    for a in range(2, n+1):
        all.append(a)               
    for b in all:                       
        for i in range(2,int(round(len(all)/b))):
            while i*b in all:
                all.remove(i*b)
                i+=1
    return all

感谢您的帮助。

BTW - 它在Python 2.7中

4 个答案:

答案 0 :(得分:1)

它不能正常工作。

主要问题是您循环使用all中的所有值,并在while中删除all中的某些元素。

这样就不会考虑all中的某些值,因此该函数不会删除所有非素数

尝试在n = 100时执行它,你得到的结果是

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99

虽然它应该是

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 (来自http://en.wikipedia.org/wiki/Prime_number

此外,第二个for的范围是错误的,因为您考虑了列表的长度,而不是b的当前值,因此您只检查前50个中的2的倍数值,前17个中的3的倍数,前9个中的5个,依此类推。从b = 13开始,您永远不会进入内部for,因为int(round(len(all)/b)) = 1因此您有类似for i in range(2,1)

的内容

答案 1 :(得分:0)

我同意Gianluca,我有一个可能的解决方案:保持你的主阵列(all)为bools并标记非素数,但不要删除它们。它也可能更快,因为您不会更改列表大小。

轻微的事情:如果你想把它作为整数,你可以在开头写all = range(2, n+1)

答案 2 :(得分:0)

您的方法会产生错误的结果。错误在于for i循环。在这里进行调整,并进行测试:

known_primes = [
2,3,5,7,11,13,17,19,23,29,
31,37,41,43,47,53,59,61,67,71,
73,79,83,89,97,101,103,107,109,113,
127,131,137,139,149,151,157,163,167,173,
179,181,191,193,197,199,211,223,227,229,
233,239,241,251,257,263,269,271,277,281,
283,293,307,311,313,317,331,337,347,349,
353,359,367,373,379,383,389,397,401,409,
419,421,431,433,439,443,449,457,461,463,
467,479,487,491,499,503,509,521,523,541,
547,557,563,569,571,577,587,593,599,601,
607,613,617,619,631,641,643,647,653,659,
661,673,677,683,691,701,709,719,727,733,
739,743,751,757,761,769,773,787,797,809,
811,821,823,827,829,839,853,857,859,863,
877,881,883,887,907,911,919,929,937,941,
947,953,967,971,977,983,991,997,1009,1013,
1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,
1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,
1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,
1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,
1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,
1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,
1453,1459,1471,1481,1483,1487,1489,1493,1499]
def eratSieve(n):
    all = []
    for a in range(2, n+1):
        all.append(a)               
    for b in all:                       
        for i in all[all.index(b):]:
            while i*b in all:
                all.remove(i*b)
                i+=1
    return all

for N in range(1500):
    for n in eratSieve(N):
        if n not in known_primes:
            print N,n

答案 3 :(得分:-1)

def primes(N):
    primes = [x for x in (2, 3, 5, 7, 11, 13) if x < N]
    if N < 17: return primes
    candidators = [x for x in xrange((N - 2) | 1, 15, -2)
                    if x % 3 and x % 5 and x % 7 and x % 11 and x % 13]
    top = int(N ** 0.5)
    while (top + 1) * (top + 1) <= N: top += 1
    while True:
        p = candidators.pop()
        primes.append(p)
        if p > top: break
        candidators = filter(p.__rmod__, candidators)
    candidators.reverse()
    primes.extend(candidators)
    return primes

我认为这段代码会更快...