进一步优化Eratosthenes的筛选

hfe*_*lan 5 optimization primes python-3.x

我已经写了一篇关于Eratosthenes的筛子 - 我认为 - 但它似乎并没有像它那样优化.它有效,并且它可以达到N的所有素数,但不会像我希望的那么快.我还在学习Python - 来自两年的Java - 所以如果某些东西不是特别Pythonic那么我道歉:

def sieve(self):
        is_prime = [False, False, True, True] + [False, True] * ((self.lim - 4) // 2)
        for i in range(3, self.lim, 2):
            if i**2 > self.lim: break
            if is_prime[i]:
                for j in range(i * i, self.lim, i * 2):
                    is_prime[j] = False
        return is_prime
Run Code Online (Sandbox Code Playgroud)

我已经查看了与此类似的其他问题,但我无法弄清楚一些更复杂的优化如何适合我的代码.有什么建议?

编辑:根据要求,我看到的一些其他优化是在限制之前停止第一个for循环的迭代,并跳过不同的数字 - 我认为是轮优化?

编辑2:这是使用该方法的代码,用于Padraic:

primes = sieve.sieve()
for i in range(0, len(primes)):
    if primes[i]:
        print("{:d} ".format(i), end = '')
print() # print a newline
Run Code Online (Sandbox Code Playgroud)

hir*_*ist 2

稍微不同的方法:使用位数组来表示奇数,3,5,7,...与布尔值列表相比节省了一些空间。

这可能只会节省一些空间,而无助于加速......

from bitarray import bitarray

def index_to_number(i): return 2*i+3
def number_to_index(n): return (n-3)//2

LIMIT_NUMBER = 50
LIMIT_INDEX = number_to_index(LIMIT_NUMBER)+1

odd_primes = bitarray(LIMIT_INDEX)
# index  0 1 2 3
# number 3 5 7 9

odd_primes.setall(True)

for i in range(LIMIT_INDEX):
    if odd_primes[i] is False:
        continue
    n = index_to_number(i)
    for m in range(n**2, LIMIT_NUMBER, 2*n):
        odd_primes[number_to_index(m)] = False

primes = [index_to_number(i) for i in range(LIMIT_INDEX)
          if odd_primes[i] is True]
primes.insert(0,2)

print('primes: ', primes)
Run Code Online (Sandbox Code Playgroud)

又是同样的想法;但这一次让 bitarray 使用切片分配来处理内部循环。这可能会更快。

for i in range(LIMIT_INDEX):
    if odd_primes[i] is False:
        continue
    odd_primes[2*i**2 + 6*i + 3:LIMIT_INDEX:2*i+3] = False
Run Code Online (Sandbox Code Playgroud)

(此代码均未经过认真检查!谨慎使用)


如果您正在寻找基于不同方法(轮因式分解)的素数生成器,请查看这个出色的答案