Answers:
有很多方法:
将任何函数的分布更改为另一个函数都涉及使用所需函数的逆函数。
换句话说,如果您针对特定的概率函数p(x),则可以通过对其积分-> d(x)=积分(p(x))并使用其反函数来获得分布:Inv(d(x)) 。现在使用随机概率函数(具有均匀分布)并通过函数Inv(d(x))转换结果值。您应该根据选择的功能获得带有分布的随机值。
这是通用的数学方法-通过使用它,您现在可以选择具有逆或良好逆近似的任何概率或分布函数。
希望这会有所帮助,并感谢您对使用分布而不是概率本身的一些评论。
这是使用Box-Muller变换的极坐标形式的javascript实现。
/*
* Returns member of set with a given mean and standard deviation
* mean: mean
* standard deviation: std_dev
*/
function createMemberInNormalDistribution(mean,std_dev){
return mean + (gaussRandom()*std_dev);
}
/*
* Returns random number in normal distribution centering on 0.
* ~95% of numbers returned should fall between -2 and 2
* ie within two standard deviations
*/
function gaussRandom() {
var u = 2*Math.random()-1;
var v = 2*Math.random()-1;
var r = u*u + v*v;
/*if outside interval [0,1] start over*/
if(r == 0 || r >= 1) return gaussRandom();
var c = Math.sqrt(-2*Math.log(r)/r);
return u*c;
/* todo: optimize this algorithm by caching (v*c)
* and returning next time gaussRandom() is called.
* left out for simplicity */
}
使用中心极限定理维基百科条目 mathworld条目可发挥您的优势。
生成n个均匀分布的数字,将它们相加,减去n * 0.5,您将得到一个近似正态分布的输出,均值等于0,方差等于(1/12) * (1/sqrt(N))
(有关最后一个的均匀分布,请参阅Wikipedia)
n = 10可以使您快得快一半。如果您想要的东西超过一半,请选择轮胎解决方案(如正态分布 Wikipedia条目中)
我会使用Box-Muller。关于以下两点:
其中R1,R2是随机统一数:
正态分布,SD为1:sqrt(-2 * log(R1))* cos(2 * pi * R2)
这是正确的……不需要执行所有这些慢循环!
八年后我可以添加一些东西似乎令人难以置信,但是对于Java,我想向读者介绍Random.nextGaussian()方法,该方法为您生成均值0.0和标准偏差1.0的高斯分布。
简单的加法和/或乘法将改变均值和标准差,以满足您的需求。
这是我从Donald Knuth的书《计算机编程的艺术》的第3.4.1节中对算法P(用于法向偏离的极坐标法)的JavaScript实现:
function normal_random(mean,stddev)
{
var V1
var V2
var S
do{
var U1 = Math.random() // return uniform distributed in [0,1[
var U2 = Math.random()
V1 = 2*U1-1
V2 = 2*U2-1
S = V1*V1+V2*V2
}while(S >= 1)
if(S===0) return 0
return mean+stddev*(V1*Math.sqrt(-2*Math.log(S)/S))
}
问:如何将均匀分布(如大多数随机数生成器产生的,例如0.0到1.0之间)转换为正态分布?
对于软件实现,我知道几个随机生成器名称,它们在[0,1]中为您提供了伪统一的随机序列(Mersenne Twister,线性一致生成器)。我们称它为U(x)
存在于数学领域中称为概率论。第一件事:如果要对具有整数分布F的rv建模,则可以尝试仅评估F ^ -1(U(x))。在理论上证明了该rv具有积分分布F。
如果可以无问题地解析得出F ^ -1,则第2步可适用于生成rv〜F,而无需使用任何计数方法。(例如exp.distribution)
为了建模正态分布,您可以计算y1 * cos(y2),其中y1〜[2pi]是均匀的。y2是relei分布。
问:如果我想选择均值和标准差怎么办?
您可以计算sigma * N(0,1)+ m。
可以证明,这种移位和缩放导致N(m,sigma)
这是使用Box-Muller变换的极坐标形式的Matlab实现:
功能randn_box_muller.m
:
function [values] = randn_box_muller(n, mean, std_dev)
if nargin == 1
mean = 0;
std_dev = 1;
end
r = gaussRandomN(n);
values = r.*std_dev - mean;
end
function [values] = gaussRandomN(n)
[u, v, r] = gaussRandomNValid(n);
c = sqrt(-2*log(r)./r);
values = u.*c;
end
function [u, v, r] = gaussRandomNValid(n)
r = zeros(n, 1);
u = zeros(n, 1);
v = zeros(n, 1);
filter = r==0 | r>=1;
% if outside interval [0,1] start over
while n ~= 0
u(filter) = 2*rand(n, 1)-1;
v(filter) = 2*rand(n, 1)-1;
r(filter) = u(filter).*u(filter) + v(filter).*v(filter);
filter = r==0 | r>=1;
n = size(r(filter),1);
end
end
调用histfit(randn_box_muller(10000000),100);
结果如下:
显然,与Matlab内置randn相比,它确实效率很低。