进一步优化Eratosthenes筛 [英] Optimize Sieve of Eratosthenes Further

查看:105
本文介绍了进一步优化Eratosthenes筛的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个Eratosthenes筛子-我认为-但似乎它没有达到最佳状态.它可以工作,并且可以将所有素数提高到N,但速度却不如我希望的那样快.我仍然在学习Python(来自Java的两年时间),因此,如果某些东西不是特别Pythonic的,我深表歉意:

I have written a Sieve of Eratosthenes--I think--but it seems like it's not as optimized as it could be. It works, and it gets all the primes up to N, but not as quickly as I'd hoped. I'm still learning Python--coming from two years of Java--so if something isn't particularly Pythonic then I apologize:

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

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

I've looked at other questions similar to this one but I can't figure out how some of the more complicated optimizations would fit in to my code. Any suggestions?

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

as requested, some of the other optimizations I've seen are stopping the iteration of the first for loop before the limit, and skipping by different numbers--which I think is wheel optimization?

这是用于Padraic的方法的代码:

EDIT 2: Here's the code that would utilize the method, for Padraic:

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

推荐答案

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

a slightly different approach: use a bitarray to represent the odd numbers 3,5,7,... saving some space compared to a list of booleans.

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

this may save some space only and not help speedup...

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)

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

the same idea again; but this time let bitarray handle the inner loop using slice assignment. this may be faster.

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

(此代码均未经过认真检查!请小心使用)

(none of this code has been seriously checked! use with care)

如果您正在寻找基于其他方法的素数生成器(车轮分解 ),请查看优秀答案.

in case you are looking for a primes generator based on a different method (wheel factorizaition) have a look at this excellent answer.

这篇关于进一步优化Eratosthenes筛的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆