zoukankan      html  css  js  c++  java
  • erlang使用gen_server实现质数服务器(手打代码,还debug了几个错误)

    最近简单了解一下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", [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
    
    
  • 相关阅读:
    Spring-Context之四:Spring容器及bean的定义
    Spring-Context之三:使用XML和Groovy DSL配置Bean
    Spring-Context之二:使用Spring提供的测试框架进行测试
    Spring-Context之一:一个简单的例子
    ActiveMQ第五弹:增加ReDelivery功能
    百度云+ KeePass 网络同步你的密码
    git生成秘钥之后同步到服务器
    谷歌chrome浏览器和火狐firefox浏览器自带http抓包工具和请求模拟插件
    ltnmp
    CentOS 下安装xdebug
  • 原文地址:https://www.cnblogs.com/andypeker/p/4631081.html
Copyright © 2011-2022 走看看