マルチスレッドで素数の計算
30分プログラム、その159。ひろ氏がお昼ご飯のときに、「マルチスレッドで素数の計算がしたい」というようなことを言っていたので、Erlangでやってみる。
方法はフェルマーテスト(id:mzp:20071001:fermat)。あるスレッドが、ほかのスレッドの計算結果に影響を受けないから、マルチスレッド向きかな、と勝手に判断。
使い方
1> c("prime.erl"). % 2から10までの素数を求める 2> prime:start(10). 2 3 5 7 true % 2から100までの素数を求める 3> prime:start(100). 2 3 5 7 11 13 15 ... ...
んー、なんか結果が間違ってる気がする。15は素数じゃないし。
ソースコード
-module(prime). -export([start/1]). % math:powは誤差が生じるし浮動小数なので、 % 整数版を定義する。 pow(_,0)-> 1; pow(X,1)-> X; pow(X,N) -> case N rem 2 of 0 -> pow(X*X,N div 2); 1 -> X*pow(X*X,N div 2) end. gcd(M,0) -> M; gcd(M,N) -> gcd(N,M rem N). % フェルマーテスト fermat(N,A)-> case gcd(N,A) of 1 -> pow(A,N-1) rem N =/= 1; _ -> false end. % N回のフェルマーテストを実行する fermat_test(From,N,0) -> From ! {prime,N}; fermat_test(From,N,Times) -> A = random:uniform(1000)+2, case fermat(N,A) of true -> From ! {not_prime,0}; false -> fermat_test(From,N,Times-1) end. % 結果を待つ wait(0) -> true; wait(M) -> receive {prime,N} -> io:format("~p~n",[N]), wait(M-1); _ -> wait(M-1) end. start(To) -> S = self(), lists:map(fun(N)-> spawn(fun()-> fermat_test(S,N,10) end) end,lists:seq(2,To)), wait(To-1).