素数を求める vol.3

Java

素数を求めるプログラムをシンプルな方法で作ってきました。

総当たり方式のものをシングルスレッドとマルチスレッドのプログラムで。

3億までの素数を検出表示させるプログラムです。

実行結果はシングルスレッドのものが約4時間半、

マルチスレッドのものが約1時間半でした。

ここで最終兵器の登場です。

エラトステネスの篩

これはどういったものかと言うと素数の性質を利用して次々と篩い落としていく感じのものです。

例えば 20 までの素数を求める場合

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

最初の 1 は素数の定義から外れるので素数ではない。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

次の 2 は当然素数の最小値である。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

と言うことは 2 の倍数である 4 6 8 10 12 14 16 18 20 は素数ではない!

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

次の 3 は消されてないから(1 と自分自身の 3 しか割り切れないから)素数である。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

同様に 3 の倍数は素数では無いので消していく。9 と 15 は素数ではない。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

次に現れる 5 は3番目の素数となる。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

同様に 5 の倍数を消していく。と言っても 5 の倍数は残ってない。

ここで 20 までと言う条件から 5 は 20 の平方根より大きいのでこれで終了になり、

残りの 7 11 13 17 19 は素数となる。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

実にシンプルで解りやすいですね。

これをプログラムにすればいいだけです。

私が最終兵器と言ったのは処理速度が先の二つのプログラムのものより異常に速いからです。

結果から先に紹介すると 3億までの素数を求めるのに1時間もかからないんです。

run:
2 is Prime Number. —> 1
3 is Prime Number. —> 2
5 is Prime Number. —> 3
7 is Prime Number. —> 4
11 is Prime Number. —> 5

     略

299999939 is Prime Number. —> 16252323
299999957 is Prime Number. —> 16252324
299999977 is Prime Number. —> 16252325
16252325個の素数を検出しました。
0時間37分10秒6889942880002309
構築成功 (合計時間: 37 分 11 秒)

今までのプログラムもこのプログラムも標準出力にすべての素数と何番目か、

それに総数と処理時間を出力していました。

ここで素数を調べるターゲットの数を非常に大きなものにし、標準出力へは

総数と処理時間を表示させるだけのものとしてパフォーマンスの違いを調べてみましょう。

では 2,147,483,640 までの素数を検出させてみます。

まず、前回の並行処理プログラムです。

jp\yucchi\primenumber\PrimeNumber.java

実行結果は次のようにかなりの時間を必要としました。( 15 時間半(;´Д`)  電気代が・・・)

run:
105097564
15時間26分32秒6862315460020909
構築成功 (合計時間: 926 分 46 秒)

では、最終兵器のエラトステネスの篩ではどうでしょうか?

jp\yucchi\primenumber_eratosthenes\PrimeNumber_Eratosthenes.java

さて、実行結果はどうなったでしょうか。

run:
105097564個の素数を検出しました。
0時間0分32秒7029516360000017
構築成功 (合計時間: 32 秒)

速っ!\(◎o◎)/!

この違いは何なんだ!

凄いぜ! エラトステネスの篩

Hatena タグ: