• erlang的随机数 及 random:uniform()函数


      每次调用会更新进程字典里的random_seed变量,这样在同一个进程内每次调用random:uniform()时,随机数种子都不同,所以生成的随机数都不一样(调用完random:uniform()后,可以用get(random_seed)查看更新后的种子值)。

    但是如果是不同的进程分别调用random:uniform(),因为随机种子更新的算法是一样的,所以每次各进程的随机数种子也是相同的,从而生成的随机数也是一样的,要想让不同进程生成的随机数不同,要手动为每个进程设置不同的种子,常用的是用erlang:now,比如:

    random:seed(erlang:now()),random:uniform().

    不过如果每个进程调用random:seed(erlang:now())太接近,种子值会比较接近,生成的随机数也会比较接近,更好的方法是用一个单独的进程来生成种子,保证每次的种子值相差比较大

    Seed = {random:uniform(99999), random:uniform(999999), random:uniform(999999)}

    然后每次调用random:uniform()前从该种子生成进程获取最新的种子值,seed()之。

    下面为random.erl 的源码:

      1 %%
      2 %% %CopyrightBegin%
      3 %% 
      4 %% Copyright Ericsson AB 1996-2011. All Rights Reserved.
      5 %% 
      6 %% The contents of this file are subject to the Erlang Public License,
      7 %% Version 1.1, (the "License"); you may not use this file except in
      8 %% compliance with the License. You should have received a copy of the
      9 %% Erlang Public License along with this software. If not, it can be
     10 %% retrieved online at http://www.erlang.org/.
     11 %% 
     12 %% Software distributed under the License is distributed on an "AS IS"
     13 %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
     14 %% the License for the specific language governing rights and limitations
     15 %% under the License.
     16 %% 
     17 %% %CopyrightEnd%
     18 %%
     19 -module(random).
     20 
     21 %% Reasonable random number generator.
     22 %%  The method is attributed to B. A. Wichmann and I. D. Hill
     23 %%  See "An efficient and portable pseudo-random number generator",
     24 %%  Journal of Applied Statistics. AS183. 1982. Also Byte March 1987.
     25 
     26 -export([seed/0, seed/1, seed/3, uniform/0, uniform/1,
     27      uniform_s/1, uniform_s/2, seed0/0]).
     28 
     29 -define(PRIME1, 30269).
     30 -define(PRIME2, 30307).
     31 -define(PRIME3, 30323).
     32 
     33 %%-----------------------------------------------------------------------
     34 %% The type of the state
     35 
     36 -type ran() :: {integer(), integer(), integer()}.
     37 
     38 %%-----------------------------------------------------------------------
     39 
     40 -spec seed0() -> ran().
     41 
     42 seed0() ->
     43     {3172, 9814, 20125}.
     44 
     45 %% seed()
     46 %%  Seed random number generation with default values
     47 
     48 -spec seed() -> ran().
     49 
     50 seed() ->
     51     case seed_put(seed0()) of
     52     undefined -> seed0();
     53     {_,_,_} = Tuple -> Tuple
     54     end.    
     55 
     56 
     57 %% seed({A1, A2, A3}) 
     58 %%  Seed random number generation 
     59 
     60 -spec seed({A1, A2, A3}) -> 'undefined' | ran() when
     61       A1 :: integer(),
     62       A2 :: integer(),
     63       A3 :: integer().
     64 
     65 seed({A1, A2, A3}) ->
     66     seed(A1, A2, A3).
     67 
     68 %% seed(A1, A2, A3) 
     69 %%  Seed random number generation 
     70 
     71 -spec seed(A1, A2, A3) -> 'undefined' | ran() when
     72       A1 :: integer(),
     73       A2 :: integer(),
     74       A3 :: integer().
     75 
     76 seed(A1, A2, A3) ->
     77     seed_put({(abs(A1) rem (?PRIME1-1)) + 1,   % Avoid seed numbers that are
     78           (abs(A2) rem (?PRIME2-1)) + 1,   % even divisors of the
     79           (abs(A3) rem (?PRIME3-1)) + 1}). % corresponding primes.
     80 
     81 
     82 -spec seed_put(ran()) -> 'undefined' | ran().
     83      
     84 seed_put(Seed) ->
     85     put(random_seed, Seed).
     86 
     87 %% uniform()
     88 %%  Returns a random float between 0 and 1.
     89 
     90 -spec uniform() -> float().
     91 
     92 uniform() ->
     93     {A1, A2, A3} = case get(random_seed) of
     94                undefined -> seed0();
     95                Tuple -> Tuple
     96            end,
     97     B1 = (A1*171) rem ?PRIME1,
     98     B2 = (A2*172) rem ?PRIME2,
     99     B3 = (A3*170) rem ?PRIME3,
    100     put(random_seed, {B1,B2,B3}),
    101     R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
    102     R - trunc(R).
    103 
    104 %% uniform(N) -> I
    105 %%  Given an integer N >= 1, uniform(N) returns a random integer
    106 %%  between 1 and N.
    107 
    108 -spec uniform(N) -> pos_integer() when
    109       N :: pos_integer().
    110 
    111 uniform(N) when is_integer(N), N >= 1 ->
    112     trunc(uniform() * N) + 1.
    113 
    114 
    115 %%% Functional versions
    116 
    117 %% uniform_s(State) -> {F, NewState}
    118 %%  Returns a random float between 0 and 1.
    119 
    120 -spec uniform_s(State0) -> {float(), State1} when
    121       State0 :: ran(),
    122       State1 :: ran().
    123 
    124 uniform_s({A1, A2, A3}) ->
    125     B1 = (A1*171) rem ?PRIME1,
    126     B2 = (A2*172) rem ?PRIME2,
    127     B3 = (A3*170) rem ?PRIME3,
    128     R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
    129     {R - trunc(R), {B1,B2,B3}}.
    130 
    131 %% uniform_s(N, State) -> {I, NewState}
    132 %%  Given an integer N >= 1, uniform(N) returns a random integer
    133 %%  between 1 and N.
    134 
    135 -spec uniform_s(N, State0) -> {integer(), State1} when
    136       N :: pos_integer(),
    137       State0 :: ran(),
    138       State1 :: ran().
    139 
    140 uniform_s(N, State0) when is_integer(N), N >= 1 ->
    141     {F, State1} = uniform_s(State0),
    142     {trunc(F * N) + 1, State1}.
    View Code

     random:seed 由进程字典put存了随机数,random:uniform则get取了随机数,而它同时又put了新的随机数.

    如果一开始直接调用,random:uniform/0,  则一开始 get(random_seed)为undefined,后面每次生产的种子的规则都是根据其业务规则生成。 但如果是 先调用random:seed/1 ,则它先生成了随机种子,put到random_seed 的进程字典中,后面依次调用random:uniform/0的时候,则从random_seed的进程字典中取出随机种子,则不是undefined,后面根据其业务规则,生成随机数.

  • 相关阅读:
    .bat文件打开指定网页,并运行jar包
    jar包制作一个可执行文件
    如何让局域网其他电脑通过IP直接访问自己电脑的网站
    Sypder 安装和使用
    tomcat服务器输入localhost可以访问,ip无法访问解决办法
    【转载】高性能网站建设
    网站优化
    JavaWeb 项目开发中的技术总结
    反射工具类——ReflectUtils
    Ajax 的缺点
  • 原文地址:https://www.cnblogs.com/unqiang/p/4180748.html
Copyright © 2020-2023  润新知