rand
rand
模块
行
模块摘要
伪随机数生成
描述
该模块提供了一个伪随机数发生器。该模块包含许多算法 xoroshiro116+ and xorshift1024* algorithms by Sebastiano Vigna.
Ziggurat Method by Marsaglia and Tsang
。均匀分布算法使用正态分布算法使用均匀分布算法的顶层。
对于某些算法,为并行计算提供了生成不重叠序列的跳变函数.。跳转函数执行等效于执行大量重复调用计算新状态的计算。
提供了下列算法:
exrop
Xoroshiro116 +,58位精度和2 ^ 116-1的周期
跳转函数:相当于2^64次调用
exs1024s
Xorshift1024 *,64位精度和2 ^ 1024-1的周期
跳转功能:相当于2 ^ 512个调用
exsp
Xorshift116 +,精度为58位,周期为2 ^ 116-1
跳转功能:相当于2 ^ 64个调用
这是以前默认算法的修正版本,现在已被Xoroshiro116 +(exrop)取代。由于没有原生的58位旋转指令,这个算法执行的速度比(比如<15%)要快一些exrop。看到了algorithms' homepage。
默认算法是exrop
(Xoroshiro116 +)。如果需要特定算法,请确保始终用于seed/1
初始化状态。
未记录(旧)算法已被弃用,但仍旧实施,因此依赖它们的旧代码将产生与以前相同的伪随机序列。
注
在实现现在未公开的算法时存在许多问题,这就是为什么它们被弃用的原因。新算法有点慢,但没有这些问题:
统一的整数范围在概率分布上有一个偏差,对于小范围来说这是不明显的,但对于大范围小于发生器的精度,产生一个低数字的概率可能是一个高概率的两倍。
统一整数范围大于或等于发生器的精度时,使用浮点回退,该回退仅使用小于请求范围的52位进行计算,因此并非所有请求范围内的数字都可能产生。
均匀的浮体具有不均匀的密度,因此小的值(即小于0.5)具有较小的间隔,随着生成的值接近0.0而减小,尽管对于足够大的子范围仍然均匀分布。新算法生成N * 2.0 ^( - 53)形式的均匀分布的浮体,因此具有相同的间距。
每次请求一个随机数时,将使用一个状态来计算它并产生一个新状态。该状态可以是隐式的,也可以是明确的参数和返回值。
具有隐式状态的函数使用进程字典变量rand_seed
来记住当前状态。
如果进程调用uniform/0
或者uniform/1
不先设置种子,seed/1
则会使用默认算法自动调用并创建非常量种子。
具有显式状态的函数从不使用进程字典。
例子:
简单的使用;如果尚未完成,则使用非常量种子创建并种子默认算法:
R0 = rand:uniform(),
R1 = rand:uniform(),
使用指定的算法:
_ = rand:seed(exs1024s),
R2 = rand:uniform(),
使用具有常量种子的指定算法:
_ = rand:seed(exs1024s, {123, 123534, 345345}),
R3 = rand:uniform(),
使用带有非常数种子的FunctionalAPI:
S0 = rand:seed_s(exrop),
{R4, S1} = rand:uniform_s(S0),
创建一个标准的正常偏差:
{SND0, S2} = rand:normal_s(S1),
创建一个平均值为3和方差为0.5的正常偏差:
{ND0, S3} = rand:normal_s(-3, 0.5, S2),
注
内置的随机数生成器算法不具有密码强度。如果需要密码强的随机数生成器,请使用类似的东西crypto:rand_seed/0
。
对于所有这些生成器,最低位(s)的随机行为比所有其他位少一些。exrop
(和exsp
)1位,以及3位exs1024s
。例如,请参阅生成器源代码中的说明: Xoroshiro128+
除了通过BigCrush之外,该生成器还通过了PractRand测试套件
直至(并包括)16TB,除二进制等级测试外,
由于最低位是LFSR而失败; 所有其他位都通过
试验。我们建议使用符号测试来提取一个随机布尔值。
如果这是一个问题;生成一个布尔类型,如下所示:
(rand:uniform(16) > 8)
对于一般范围,N = 1
用于exrop
和N = 3
为exs1024s
:
(((rand:uniform(Range bsl N) - 1) bsr N) + 1)
当从一个整数转换时,这个模块中的浮点生成函数浪费最小的位,所以它们避免了这个障碍。
数据类型
builtin_alg() =
exs64 | exsplus | exsp | exs1024 | exs1024s | exrop
alg() =
builtin_alg()
| atom()
alg_handler() =
#{type :=
alg()
,
bits => integer() >= 0,
weak_low_bits => integer() >= 0,
max => integer() >= 0,
next :=
fun((alg_state()) -> {integer() >= 0,alg_state()}),
uniform => fun((state()) -> {float(),state()}),
uniform_n =>
fun((integer() >= 1,state()) -> {integer() >= 1,state()}),
jump => fun((state()) ->state())}
alg_state() =
exs64_state()
|
exsplus_state()
|
exs1024_state()
|
exrop_state()
|
term()
state() = {
alg_handler()
,
alg_state()
}
算法依赖状态。
export_state() = {
alg()
,
alg_state()
}
算法依赖状态,可以打印或保存到文件中。
exs64_state()
算法特定内部状态
exsplus_state()
算法特定内部状态
exs1024_state()
算法特定内部状态
exrop_state()
算法特定内部状态
出口
export_seed() -> undefined | export_state()
以外部格式返回随机数字状态。与...一起使用seed/1
。
export_seed_s(State :: state()) -> export_state()
以外部格式返回随机数生成器状态。与...一起使用seed/1
。
jump() -> NewState :: state()
在执行跳转计算到流程字典中的状态之后,返回状态。
如果not_implemented
没有为流程字典中的状态指定的算法实施跳转功能,则此函数会生成错误异常。
jump(State :: state()) -> NewState :: state()
返回执行跳转计算到给定状态后的状态。
not_implemented
当在该状态下指定的算法没有实现跳转功能时,该函数会生成一个错误异常。
normal() -> float()
返回标准的正常偏差浮点数(即平均值为0,标准偏差为1),并更新过程字典中的状态。
normal(Mean :: number(), Variance :: number()) -> float()
返回一个正常的N(Mean,Variance)偏离浮点数并更新流程字典中的状态。
normal_s(State :: state()) -> {float(), NewState :: state()}
对于指定的状态,返回标准正常偏离的浮点数(即平均值为0,标准偏差为1)和新状态。
normal_s(Mean :: number(),
Variance :: number(),
State0 :: state()) ->
{float(), NewS :: state()
}
对于指定的状态,返回正常的N(平均值,方差)偏差浮动值和新的状态值。
seed(AlgOrStateOrExpState ::
builtin_alg() | state() | export_state()) ->
state()
如果AlgOrStateOrExpState
是算法,则使用指定的算法和随时间变化的数据来生成随机数生成。
否则在流程字典中重新创建导出的种子,并返回状态。另见export_seed/0
。
seed(Alg :: builtin_alg()
,
Seed :: {integer(), integer(), integer()}) ->
state()
使用指定的算法和进程字典中的整数种子随机数生成并返回状态。
seed_s(AlgOrStateOrExpState ::
builtin_alg() | state() | export_state()) ->
state()
如果AlgOrStateOrExpState
是算法,则使用指定的算法和随时间变化的数据来生成随机数生成。
否则,重新创建导出的种子并返回状态。另见export_seed/0
。
seed_s(Alg :: builtin_alg()
,
Seed :: {integer(), integer(), integer()}) ->
state()
用指定的算法和整数种子随机数生成并返回状态。
uniform() -> X :: float()
返回均匀分布在值范围内的随机float,0.0 =< X < 1.0并更新进程字典中的状态。
生成的数字形式为N * 2.0 ^( - 53),即; 在间隔中等间隔。
警告
这个函数可能会返回0.0到某些应用程序可能致命的地方。如果这是不希望的,你可以用它(1.0 - rand:uniform())来获得间隔0.0 < X =< 1.0。
如果两个端点都不需要,您可以测试并重新尝试,如下所示:
my_uniform() ->
case rand:uniform() of
0.0 -> my_uniform(
X -> X
end
end.
uniform(N :: integer() >= 1) -> X :: integer() >= 1
对于指定的整数N >= 1,返回一个均匀分布在值范围内的随机整数,1 =< X =< N并更新流程字典中的状态。
uniform_s(State :: state()) -> {X :: float(), NewState :: state()}
对于指定状态,返回均匀分布在值范围0.0 =< X < 1.0和新状态中的随机float 。
生成的数字形式为N * 2.0 ^( - 53),即;在间隔中等间隔。
警告
这个函数可能会返回0.0到某些应用程序可能致命的地方。如果这是不希望的,你可以用它(1.0 - rand:uniform(State))来获得间隔0.0 < X =< 1.0。
如果两个端点都不需要,您可以测试并重新尝试,如下所示:
my_uniform(State) ->
case rand:uniform(State) of
{0.0, NewState} -> my_uniform(NewState
Result -> Result
end
end.
uniform_s(N :: integer() >= 1, State :: state()) ->
{X :: integer() >= 1, NewState :: state()}
对于指定的整数N >= 1和状态,返回一个在值范围内均匀分布的随机整数1 =< X =< N和一个新状态。