エラトステネスの篩で素数列挙【Python】
ある値以下の素数を列挙する方法のひとつにエラトステネスの篩(ふるい)があります。
この記事ではPythonでエラトステネスの篩をプログラミングしていきます。
エラトステネスの篩とは
次のように整数n以下の素数を高速にすべて列挙する方法です。
まず2からnまでの数を考え、この数字のなかで最も小さい数字をpとおき、n以下かつp以外のpの倍数をすべて消していきます。
消し終えたら、その中で最も小さい数字をpとおき倍数を消していく・・・という作業を繰り返します。
pが√nを超えたら終了です。
このときに残った数字が素数になります。
素数列挙プログラム(n = 100の場合)
# x以下の素数列挙 def sieve_of_eratosthenes(x): nums = [i for i in range(x+1)] root = int(pow(x,0.5)) for i in range(2,root + 1): if nums[i] != 0: for j in range(i, x+1): if i*j >= x+1: break nums[i*j] = 0 primes = sorted(list(set(nums)))[2:] return primes p = sieve_of_eratosthenes(100) print(p) # --> [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] print(len(p)) # --> 25
解説
nums[i] = iとなる配列を作成して素数の列挙をすすめていきます。
エラトステネスの篩は√nより大きい数字になれば終了してよいのでrootに√nを計算し、このrootを用いてループの範囲は2からroot + 1として進めます。
nums[i]が0なら次の数字にスキップし、0でなければさらにループさせ倍数を削除します。
2重ループではp[i]の倍数であるi × jを0に置き換えました。(nums[i*j] = 0)
この探索を終えるとnumsに残る値は素数か0です。
0が複数あるnumsをset(nums)としてset型を利用して0の重複を削除しました。
このset(nums)を再度list()でリスト化し、ソートします。
これで[0, 1, 2, 3, 5, 7… ,97]という配列になるので、不要になる初めの2つの要素をスライスして取り除きます。
その結果、primes = sorted(list(set(nums)))[2:] = [2, 3, 5, 7… ,97]という求める素数を列挙した配列を作成できました。
primesをlen()で個数を調べることで素数の数を数えることもできます。
上記のプログラムで高速に素数を列挙することができました!
エラトステネスの篩についてこちらの記事が参考になりました。
ありがとうございました。
club.informatix.co.jp