标签:
最近简单了解一下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) ->
11 %% gen_server:call(?MODULE, {?MODULE, N}, 20000).
12 gen_server:call(?MODULE, {prime, N}, 20000).
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>
erlang使用gen_server实现质数服务器(手打代码,还debug了几个错误)
标签:
原文地址:http://www.cnblogs.com/andypeker/p/4631081.html