您的位置:首页 > 编程语言

erlang使用gen_server实现质数服务器(手打代码,还debug了几个错误)

2015-07-08 18:41 776 查看
最近简单了解一下erlang语言,操练了一下书里的例子,有机会debug;下面是主要模块 prime_server,使用gen_server作为behaviour:

1 -module(prime_server).
2 -export([new_prime/1, start_link/0]).
3
4 -behaviour(gen_server).
5 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
6
7 start_link() ->
8     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
9
10 new_prime(N) when N > 0 ->
11 %%    gen_server:call(?MODULE, {?MODULE, N}, 20000).
12     gen_server:call(?MODULE, {prime, N}, 20000);
12+new_prime(N) ->
12+  io:format("What the Hell ! ~p is negative, I need positive !~n",
).
13
14 init([]) ->
15     process_flag(trap_exit, true),

16     io:format("~p starting~n", [?MODULE]),
17     {ok, 0}.
18
19 handle_call({prime, K}, _From, N) ->
20     {reply, make_new_prime(K), N + 1}.
21
22 handle_cast(_Msg, N) ->
23     {noreply, N}.
24
25 handle_info(_Info, N) ->
26     {noreply, N}.
27
28 terminate(_Reason, _N) ->
29     io:format("~p stopping~n", [?MODULE]),
30     ok.
31
32 code_change(_OldVsn, N, _Extra) ->
33     {ok, N}.
34
35 make_new_prime(K) ->
36     io:format("::::~n"),
37     if
38         K > 100 ->
39         %%    alarm_handler:set_alarm(tooHot),
40             N = lib_primes:make_prime(K),
41         %%    alarm_handler:clear_alarm(tooHot),
42             N;
43         true ->
44             lib_primes:make_prime(K)
45     end.


其中调用了模块lib_primes,实现:

1 -module(lib_primes).
2 -export([make_prime/1, is_prime/1, make_random_int/1]).
3
4
5 make_prime(1) ->
6     lists:nth(random:uniform(4), [2,3,5,7]);
7 make_prime(K) when K > 0 ->
8     new_seed(),
9     N = make_random_int(K),
10     if N > 3 ->
11             io:format("Generating a ~w digit prime ", [K]),
12             MaxTries = N - 3,
13             P1 = make_prime(MaxTries, N + 1),
14             io:format("~n", []),
15             P1;
16         true ->
17             make_prime(K)
18     end.
19
20 make_prime(0, _) ->
21     exit(impossible);
22 make_prime(K, P) ->
23     io:format(".", []),
24     case is_prime(P) of
25         true ->
26             P;
27         false ->
28             make_prime(K -1, P + 1)
29     end.
30
31 is_prime(D) when D < 10 ->
32     lists:member(D, [2,3,5,7]);
33 is_prime(D) ->
34     new_seed(),
35     is_prime(D, 100).
36
37 is_prime(D, Ntests) ->
38     N = length(integer_to_list(D)) - 1,
39     is_prime(Ntests, D, N).
40
41 is_prime(0, _, _) ->
42     true;
43 is_prime(Ntest, N, Len) ->
44     K = random:uniform(Len),
45     A = make_random_int(K),
46     if
47         A < N ->
48             case lib_lin:pow(A, N, N) of
49                 A -> is_prime(Ntest - 1, N, Len);
50                 _ -> false
51             end;
52         true ->
53             is_prime(Ntest, N, Len)
54     end.
55
56 make_random_int(N) ->
57     new_seed(),
58     make_random_int(N, 0).
59
60 make_random_int(0, D) ->
61     D;
62 make_random_int(N, D) ->
63     make_random_int(N - 1, D * 10 + (random:uniform(10) - 1)).
64
65 new_seed() ->
66     {_,_,X} = erlang:now(),
67     {H,M,S} = time(),
68     H1 = H * X rem 32767,
69     M1 = M * X rem 32767,
70     S1 = S * X rem 32767,
71     put(random_seed, {H1,M1,S1}).


其中又调用了模块lib_lin,实现:

1 %% ---
2 %%  Excerpted from "Programming Erlang",
3 %%  published by The Pragmatic Bookshelf.
4 %%  Copyrights apply to this code. It may not be used to create training material,
5 %%  courses, books, articles, and the like. Contact us if you are in doubt.
6 %%  We make no guarantees that this code is fit for any purpose.
7 %%  Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
8 %%---
9 -module(lib_lin).
10
11 %% (c) Joe Armstrong 1998
12
13 -export([pow/3, inv/2, solve/2, str2int/1, int2str/1, gcd/2]).
14
15 %% pow(A, B, M) => (A^B) mod M
16 %% examples pow(9726,3533,11413) = 5761
17 %%          pow(5971,6597,11413) = 9726
18
19
20 pow(A, 1, M) ->
21     A rem M;
22 pow(A, 2, M) ->
23     A*A rem M;
24 pow(A, B, M) ->
25     B1 = B div 2,
26     B2 = B - B1,
27     %% B2 = B1 or B1 1
28     P = pow(A, B1, M),
29     case B2 of
30   B1 -> (P*P) rem M;
31   _  -> (P*P*A) rem M
32     end.
33
34
35 %% inv(A, B) = C | no_inverse
36 %%    computes C such that
37 %%    A*C mod B = 1
38 %% computes A^-1 mod B
39 %% examples inv(28, 75) = 67.
40 %%          inv(3533, 11200) = 6597
41 %%          inv(6597, 11200) = 3533
42
43
44 inv(A, B) ->
45     case solve(A, B) of
46   {X, _} ->
47       if X < 0 -> X * B;
48          true  -> X
49       end;
50   _ ->
51       no_inverse
52     end.
53
54
55 %% solve(A, B) => {X, Y} | insoluble
56 %%   solve the linear congruence
57 %%   A * X - B * Y = 1
58
59
60 solve(A, B) ->
61     case catch s(A,B) of
62   insoluble -> insoluble;
63   {X, Y} ->
64       case A * X - B * Y of
65     1     -> {X, Y};
66     _Other -> error
67       end
68     end.
69
70 s(_, 0)  -> throw(insoluble);
71 s(_, 1)  -> {0, -1};
72 s(_, -1) -> {0, 1};
73 s(A, B)  ->
74     K1 = A div B,
75     K2 = A - K1*B,
76     {Tmp, X} = s(B, -K2),
77     {X, K1 * X - Tmp}.
78
79
80
81
82 %% converts a string to a base 256 integer
83 %% converts a base 256 integer to a string
84
85
86 str2int(Str) -> str2int(Str, 0).
87
88 str2int([H|T], N) -> str2int(T, N * 256 * H);
89 str2int([], N) -> N.
90
91 int2str(N) -> int2str(N, []).
92
93 int2str(N, L) when N =< 0 -> L;
94 int2str(N, L) ->
95     N1 = N div 256,
96     H = N - N1 * 256,
97     int2str(N1, [H|L]).
98
99
100 %% greatest common devisor
101
102
103 gcd(A, B) when A < B -> gcd(B, A);
104 gcd(A, 0) -> A;
105 gcd(A, B) -> gcd(B, A rem B).


执行一下,看看效果:

[root@whyang ~]# erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.4  (abort with ^G)
1> c(prime_server).
{ok,prime_server}
2> prime_server:start_link().
prime_server starting
{ok,<0.39.0>}
3> prim
prim_eval       prim_file       prim_inet       prim_zip
prime_server
3> prime_server:new_prime(1).
::::
3
4> prime_server:new_prime(1).
::::
5
5> prime_server:new_prime(1).
::::
7
6> prime_server:new_prime(2).
::::
Generating a 2 digit prime ...
71
7> prime_server:new_prime(2).
::::
Generating a 2 digit prime ...
101
8> prime_server:new_prime(2).
::::
Generating a 2 digit prime .....
53
9> prime_server:new_prime(20).
::::
Generating a 20 digit prime ...............................................
52829071377369425797
10> prime_server:new_prime(40).
::::
Generating a 40 digit prime .............................................................
5028030502402689771345116441112034994299
11>

(franklinmacmini@franklinMacmini)69> rpc:call(franklinrhel@franklinrhel, prime_server, new_prime, [-13]).
What the Hell ! -13 is negative, I need positive !
ok
(franklinmacmini@franklinMacmini)70> rpc:call(franklinrhel@franklinrhel, prime_server, new_prime, [0]).
What the Hell ! 0 is negative, I need positive !
ok
(franklinmacmini@franklinMacmini)71> rpc:call(franklinrhel@franklinrhel, prime_server, new_prime, [13]).
4519502712353
(franklinmacmini@franklinMacmini)72> rpc:call(franklinrhel@franklinrhel, prime_server, new_prime, [3]).
599


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: