如果使用相同的种子,为什么 Erlang 会生成相同的随机数序列?
Why does Erlang generate the same sequence of random number if applying the same seed?
我将以下命令应用于两个 erlang 提示符,它们都生成相同的随机数序列,那么这是否意味着它是 Erlang 语言中的伪随机数?我很好奇其中的原理,因为在 Java 中,即使我为它提供两次相同的种子,序列也不会相同。非常感谢!
random:seed(6, 6, 6).
random:uniform(100).
random:uniform(100).
...
the generated sequence: 12, 27, 79, 58, 90, 25, ...
您所描述的通常是传统伪运行dom 数字生成器 (PRNG) 一直以来的工作方式,包括 Erlang 的 random
模块,我认为它实现了 Wichman-Hill, but today's PRNGs are necessarily more sophisticated. In Erlang 18 you'll find a new rand
module不会遇到您描述的问题。
从下面复制的shell session可以看出,可以直接从不同的进程中调用rand:uniform/0,1
函数而不做种,而且各个进程中的初始编号会不同:
1> rand:uniform().
0.10584199892675317
2> Self = self().
<0.1573.0>
3> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.9124422823012622
4> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.9476479571869831
5> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.037189460750910064
6> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.17698653918897836
第一个调用直接在 shell 进程中运行。然后我们获取 shell 的 pid,将其存储到 Self
,并连续生成四个进程,每个进程将 rand:uniform/0
的结果发送回 shell,后者接收它变成 R
。如您所见,四个派生的进程每个 return 不同的值,所有这些值都不同于 shell 在它第一次 运行 rand:uniform/0
.[=27= 时获得的值]
如果您想要 运行ge 中的数字不是 0-1,请将整数 N
传递给 rand:uniform/1
,您将得到一个值 V
在 运行ge 1 <= V
<= N
:
7> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
510226
8> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
562646
9> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
250637
10> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
820871
11> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
121252
我将以下命令应用于两个 erlang 提示符,它们都生成相同的随机数序列,那么这是否意味着它是 Erlang 语言中的伪随机数?我很好奇其中的原理,因为在 Java 中,即使我为它提供两次相同的种子,序列也不会相同。非常感谢!
random:seed(6, 6, 6).
random:uniform(100).
random:uniform(100).
...
the generated sequence: 12, 27, 79, 58, 90, 25, ...
您所描述的通常是传统伪运行dom 数字生成器 (PRNG) 一直以来的工作方式,包括 Erlang 的 random
模块,我认为它实现了 Wichman-Hill, but today's PRNGs are necessarily more sophisticated. In Erlang 18 you'll find a new rand
module不会遇到您描述的问题。
从下面复制的shell session可以看出,可以直接从不同的进程中调用rand:uniform/0,1
函数而不做种,而且各个进程中的初始编号会不同:
1> rand:uniform().
0.10584199892675317
2> Self = self().
<0.1573.0>
3> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.9124422823012622
4> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.9476479571869831
5> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.037189460750910064
6> f(R), spawn(fun() -> Self ! rand:uniform() end), receive R -> R end.
0.17698653918897836
第一个调用直接在 shell 进程中运行。然后我们获取 shell 的 pid,将其存储到 Self
,并连续生成四个进程,每个进程将 rand:uniform/0
的结果发送回 shell,后者接收它变成 R
。如您所见,四个派生的进程每个 return 不同的值,所有这些值都不同于 shell 在它第一次 运行 rand:uniform/0
.[=27= 时获得的值]
如果您想要 运行ge 中的数字不是 0-1,请将整数 N
传递给 rand:uniform/1
,您将得到一个值 V
在 运行ge 1 <= V
<= N
:
7> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
510226
8> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
562646
9> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
250637
10> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
820871
11> f(R), spawn(fun() -> Self ! rand:uniform(1234567) end), receive R -> R end.
121252