erlang的随机数 及 random:uniform()函数
2014-12-23 18:56
344 查看
每次调用会更新进程字典里的random_seed变量,这样在同一个进程内每次调用random:uniform()时,随机数种子都不同,所以生成的随机数都不一样(调用完random:uniform()后,可以用get(random_seed)查看更新后的种子值)。
但是如果是不同的进程分别调用random:uniform(),因为随机种子更新的算法是一样的,所以每次各进程的随机数种子也是相同的,从而生成的随机数也是一样的,要想让不同进程生成的随机数不同,要手动为每个进程设置不同的种子,常用的是用erlang:now,比如:
不过如果每个进程调用random:seed(erlang:now())太接近,种子值会比较接近,生成的随机数也会比较接近,更好的方法是用一个单独的进程来生成种子,保证每次的种子值相差比较大:
然后每次调用random:uniform()前从该种子生成进程获取最新的种子值,seed()之。
下面为random.erl 的源码:
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,后面根据其业务规则,生成随机数.
但是如果是不同的进程分别调用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 的源码:
%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% -module(random). %% Reasonable random number generator. %% The method is attributed to B. A. Wichmann and I. D. Hill %% See "An efficient and portable pseudo-random number generator", %% Journal of Applied Statistics. AS183. 1982. Also Byte March 1987. -export([seed/0, seed/1, seed/3, uniform/0, uniform/1, uniform_s/1, uniform_s/2, seed0/0]). -define(PRIME1, 30269). -define(PRIME2, 30307). -define(PRIME3, 30323). %%----------------------------------------------------------------------- %% The type of the state -type ran() :: {integer(), integer(), integer()}. %%----------------------------------------------------------------------- -spec seed0() -> ran(). seed0() -> {3172, 9814, 20125}. %% seed() %% Seed random number generation with default values -spec seed() -> ran(). seed() -> case seed_put(seed0()) of undefined -> seed0(); {_,_,_} = Tuple -> Tuple end. %% seed({A1, A2, A3}) %% Seed random number generation -spec seed({A1, A2, A3}) -> 'undefined' | ran() when A1 :: integer(), A2 :: integer(), A3 :: integer(). seed({A1, A2, A3}) -> seed(A1, A2, A3). %% seed(A1, A2, A3) %% Seed random number generation -spec seed(A1, A2, A3) -> 'undefined' | ran() when A1 :: integer(), A2 :: integer(), A3 :: integer(). seed(A1, A2, A3) -> seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are (abs(A2) rem (?PRIME2-1)) + 1, % even divisors of the (abs(A3) rem (?PRIME3-1)) + 1}). % corresponding primes. -spec seed_put(ran()) -> 'undefined' | ran(). seed_put(Seed) -> put(random_seed, Seed). %% uniform() %% Returns a random float between 0 and 1. -spec uniform() -> float(). uniform() -> {A1, A2, A3} = case get(random_seed) of undefined -> seed0(); Tuple -> Tuple end, B1 = (A1*171) rem ?PRIME1, B2 = (A2*172) rem ?PRIME2, B3 = (A3*170) rem ?PRIME3, put(random_seed, {B1,B2,B3}), R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3, R - trunc(R). %% uniform(N) -> I %% Given an integer N >= 1, uniform(N) returns a random integer %% between 1 and N. -spec uniform(N) -> pos_integer() when N :: pos_integer(). uniform(N) when is_integer(N), N >= 1 -> trunc(uniform() * N) + 1. %%% Functional versions %% uniform_s(State) -> {F, NewState} %% Returns a random float between 0 and 1. -spec uniform_s(State0) -> {float(), State1} when State0 :: ran(), State1 :: ran(). uniform_s({A1, A2, A3}) -> B1 = (A1*171) rem ?PRIME1, B2 = (A2*172) rem ?PRIME2, B3 = (A3*170) rem ?PRIME3, R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3, {R - trunc(R), {B1,B2,B3}}. %% uniform_s(N, State) -> {I, NewState} %% Given an integer N >= 1, uniform(N) returns a random integer %% between 1 and N. -spec uniform_s(N, State0) -> {integer(), State1} when N :: pos_integer(), State0 :: ran(), State1 :: ran(). uniform_s(N, State0) when is_integer(N), N >= 1 -> {F, State1} = uniform_s(State0), {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,后面根据其业务规则,生成随机数.
相关文章推荐
- Erlang的random:uniform()函数
- AS使用Random函数创建随机数
- 原来c++中没有random()函数,而是用rand函数实现产生随机数的功能
- iOS 中生成随机数的4种方法(rand、random、arc4random、arc4random_uniform)
- Python生成随机数与random模块中最常用的几个函数
- tensorflow生成随机数的操作 tf.random_normal & tf.random_uniform & tf.truncated_normal & tf.random_shuffle
- java中用来生成随机数的函数:Random()
- 使用Random函数创建随机数
- AS使用Random函数创建随机数
- 随机数生成 arc4random_uniform(_:UInt32) ->UInt32
- numpy.random模块中提供啦大量的随机数相关的函数
- 使用Random函数产生随机数
- js生成随机数之random函数随机示例
- js生成随机数之random函数随机示例
- Swift - 使用arc4random()、arc4random_uniform()取得随机数
- 设计程序,单击【随机数】按钮,使用Math对象的random函数产生一个0-100之间(含0-100)的随机整数,并在对话框中显示,如下图。单击【计算】按钮,计算该随机数的平方、平方根和自然对数,保留两位小数,并在对话框中显示,如下图。
- AS使用Random函数创建随机数
- 12.java 中的随机数 Random类和 Math 中 random()函数
- Math.random()函数随机数取值机制
- Swift - 使用arc4random()、arc4random_uniform()取得随机数