エラトステネスのふるいkは、次のように限界まで素数を生成する適度に高速な方法です。
p = (2, 3, 4, ..., k)セットとから始めi = 2ます。- から始めて、からの
i^2すべての倍数を削除します。ip iの次に小さいものについてp、まで繰り返しi >= sqrt(k)ます。
私の現在の実装は次のようになります(すべての偶数を事前にフィルタリングするという明らかな最適化を使用):
# Compute all prime numbers less than k using the Sieve of Eratosthenes
def sieve(k):
s = set(range(3, k, 2))
s.add(2)
for i in range(3, int(sqrt(k)), 2):
if i in s:
for j in range(i ** 2, k, i * 2):
s.discard(j)
return sorted(s)
編集:これは同等のlistベースのコードです:
def sieve_list(k):
s = [True] * k
s[0] = s[1] = False
for i in range(4, k, 2):
s[i] = False
for i in range(3, int(sqrt(k)) + 2, 2):
if s[i]:
for j in range(i ** 2, k, i * 2):
s[j] = False
return [2] + [ i for i in range(3, k, 2) if s[i] ]
これは機能しますが、完全には正しくありません。台詞:
for i in range(3, int(sqrt(k)), 2):
if i in s:
[...]
s奇数ごとにセットメンバーシップをテストして、の次に小さい要素を見つけます。理想的には、実装は実際には次のようになります。
while i < sqrt(k):
[...]
i = next smallest element in s
ただし、setは順序付けされていないため、次に小さい要素をより効率的に取得する方法がわかりません(または可能であっても)。list素数にwith True/フラグを使用することを検討しましたFalseが、それでも次の要素listを探して歩く必要があります。Trueどちらかから実際に要素を削除することはできませんlist。これにより、手順2で合成数を効率的に削除できなくなります。
次に小さい要素をより効率的に見つける方法はありますか?そうでない場合、O(1)値による削除と次に小さい要素を見つける効率的な方法を可能にする他のデータ構造はありますか?