Man*_*oxx 47 javascript random algorithm distribution gaussian
我想知道JavaScript函数是否Math.random使用普通(与统一)分布.
如果没有,我如何获得使用正态分布的数字?我没有在互联网上找到一个明确的答案,一个算法来创建随机的正态分布数字.
我想重建施密特机器(德国物理学家).机器产生0或1的随机数,它们必须是正态分布的,这样我才能将它们绘制成高斯钟形曲线.
例如,随机函数产生120个数字(0或1),并且这些求和值的平均值(平均值)必须接近60.
Max*_*ard 107
由于这是我经验中"js高斯随机"的第一个Google结果,我觉得有义务给出该查询的实际答案.
所述盒-缪勒变换转换两个独立的均匀个变量上(0,1)分成两个标准高斯分布随机数(平均值为0,方差为1).这可能是不很高性能的,因为的sqrt,log和cos呼叫,但这种方法是优于中心极限定理方法(求和Ñ均匀个变量),因为它不限制输出到有限范围(-N/2, N/2).这也很简单:
// Standard Normal variate using Box-Muller transform.
function randn_bm() {
var u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}
Run Code Online (Sandbox Code Playgroud)
jos*_*ell 60
在麦克斯韦答案的基础上,此代码使用Box-Muller变换为您提供0到1之间的正态分布.它只是重新取样值,如果它超过3.6标准偏差(小于0.02%的几率).
function randn_bm() {
var u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
num = num / 10.0 + 0.5; // Translate to 0 -> 1
if (num > 1 || num < 0) return randn_bm(); // resample between 0 and 1
return num;
}
Run Code Online (Sandbox Code Playgroud)
n = 100
n = 10,000
n = 10,000,000
此版本允许您提供最小值,最大值和倾斜因子.请参阅底部的我的用法示例.
function randn_bm(min, max, skew) {
var u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
num = num / 10.0 + 0.5; // Translate to 0 -> 1
if (num > 1 || num < 0) num = randn_bm(min, max, skew); // resample between 0 and 1 if out of range
num = Math.pow(num, skew); // Skew
num *= max - min; // Stretch to fill range
num += min; // offset to min
return num;
}
Run Code Online (Sandbox Code Playgroud)
randn_bm(-500, 1000, 1);
Run Code Online (Sandbox Code Playgroud)
randn_bm(10, 20, 0.25);
Run Code Online (Sandbox Code Playgroud)
randn_bm(10, 20, 3);
Run Code Online (Sandbox Code Playgroud)
kod*_*vin 44
我想知道JavaScript函数Math.random是否是正态分布
使用Javascript的Math.random 是 不是一个正态分布(高斯钟形曲线).来自 ES 2015,20.2.2.27 "使用依赖于实现的算法或策略,返回具有正号,大于或等于0但小于1的数字值,随机或伪随机选择,在该范围内具有近似均匀分布.函数不带参数." 因此,当n足够高时,所提供的集合将得到近似均匀的分布.区间中的所有值都具有相同的出现概率(与x轴平行的直线,表示介于0.0和1.0之间的数字).
如何获得正态分布的数字
有几种方法可以收集正态分布的数字.正如Maxwell Collard所回答的那样,Box-Muller变换 确实将均匀分布转换为正态分布(代码可以在Maxwell Collard答案中找到).
另一个计算器回答一个答案的问题与其他均匀分布正态分布算法的答复.如:Ziggurat,制服比率,反转CDF除了其中一个答案之外:说:
Ziggurat算法对此非常有效,尽管Box-Muller变换更容易从头开始实现(而不是疯狂慢).
最后
我想重建施密特机器(德国物理学家),机器产生0或1的随机数,它们必须是正态分布的,所以我可以用高斯钟形曲线绘制它们.
当我们只有两个值(0或1)时,高斯曲线看起来与具有2个可能值的均匀分布相同.这就是为什么简单
function randomZero_One(){
return Math.round(Math.random());
}
Run Code Online (Sandbox Code Playgroud)
就够了 它将以大致相等的概率值0和1伪随机返回.
Dor*_*ian 40
我希望在0和1之间有大约高斯随机数,经过多次测试后我发现这是最好的:
function gaussianRand() {
var rand = 0;
for (var i = 0; i < 6; i += 1) {
rand += Math.random();
}
return rand / 6;
}
Run Code Online (Sandbox Code Playgroud)
作为奖励:
function gaussianRandom(start, end) {
return Math.floor(start + gaussianRand() * (end - start + 1));
}
Run Code Online (Sandbox Code Playgroud)
小智 17
Javascript Math.random()伪随机函数返回在0和1之间均匀分布的变量.为了获得高斯分布,我使用:
// returns a gaussian random function with the given mean and stdev.
function gaussian(mean, stdev) {
var y2;
var use_last = false;
return function() {
var y1;
if(use_last) {
y1 = y2;
use_last = false;
}
else {
var x1, x2, w;
do {
x1 = 2.0 * Math.random() - 1.0;
x2 = 2.0 * Math.random() - 1.0;
w = x1 * x1 + x2 * x2;
} while( w >= 1.0);
w = Math.sqrt((-2.0 * Math.log(w))/w);
y1 = x1 * w;
y2 = x2 * w;
use_last = true;
}
var retval = mean + stdev * y1;
if(retval > 0)
return retval;
return -retval;
}
}
// make a standard gaussian variable.
var standard = gaussian(100, 15);
// make a bunch of standard variates
for(i=0; i<2000; i++) {
console.log(standard());
}
Run Code Online (Sandbox Code Playgroud)
我想我是从Knuth得到的.
Joe*_*Joe 12
利用中心极限定理的函数.
function normal(mu, sigma, nsamples){
if(!nsamples) nsamples = 6
if(!sigma) sigma = 1
if(!mu) mu=0
var run_total = 0
for(var i=0 ; i<nsamples ; i++){
run_total += Math.random()
}
return sigma*(run_total - nsamples/2)/(nsamples/2) + mu
}
Run Code Online (Sandbox Code Playgroud)
你混淆函数的输出(这是0和1之间的均匀分布)需要通过重复绘制0或1的随机数来生成高斯分布 - 在大量试验之后,它们的总和将是近似正态分布.
您可以使用该Math.random()函数,然后将结果舍入为整数:如果它<0.5,则返回0; 如果它> = 0.5,则返回1.现在你有相同的概率为零和一,你可以继续你在问题中描述的方法.
只是为了澄清:我认为不可能有一个以正态分布方式产生0或1的算法 - 正态分布需要连续变量.
当您执行上述120个数字时,您将平均得到60个1和60个0.您获得的实际分布将是二项分布,平均值为60,标准差为
stdev = sqrt(p(1-p)N) = 5.48
Run Code Online (Sandbox Code Playgroud)
k当你有可能的n样本p(我们固定为0.5)时,特定数字的概率是
p = n! / ((n-k)! k!) p^k (1-p)^(n-k)
Run Code Online (Sandbox Code Playgroud)
当p = 0.5时,你最终只得到二项式系数 - 通常接近n> 30的正态分布.
还有一个单行示例:
Math.sqrt(-2 * Math.log(Math.random()))*Math.cos((2*Math.PI) * Math.random())
Run Code Online (Sandbox Code Playgroud)
和小提琴 https://jsfiddle.net/rszgjqf8/
对于那些对生成正态分布值感兴趣的人,我建议在 JavaScript 中检查 Ziggurat 算法的这种实现:https ://www.npmjs.com/package/node-ziggurat
在作者页面中找到的代码是:
function Ziggurat(){
var jsr = 123456789;
var wn = Array(128);
var fn = Array(128);
var kn = Array(128);
function RNOR(){
var hz = SHR3();
var iz = hz & 127;
return (Math.abs(hz) < kn[iz]) ? hz * wn[iz] : nfix(hz, iz);
}
this.nextGaussian = function(){
return RNOR();
}
function nfix(hz, iz){
var r = 3.442619855899;
var r1 = 1.0 / r;
var x;
var y;
while(true){
x = hz * wn[iz];
if( iz == 0 ){
x = (-Math.log(UNI()) * r1);
y = -Math.log(UNI());
while( y + y < x * x){
x = (-Math.log(UNI()) * r1);
y = -Math.log(UNI());
}
return ( hz > 0 ) ? r+x : -r-x;
}
if( fn[iz] + UNI() * (fn[iz-1] - fn[iz]) < Math.exp(-0.5 * x * x) ){
return x;
}
hz = SHR3();
iz = hz & 127;
if( Math.abs(hz) < kn[iz]){
return (hz * wn[iz]);
}
}
}
function SHR3(){
var jz = jsr;
var jzr = jsr;
jzr ^= (jzr << 13);
jzr ^= (jzr >>> 17);
jzr ^= (jzr << 5);
jsr = jzr;
return (jz+jzr) | 0;
}
function UNI(){
return 0.5 * (1 + SHR3() / -Math.pow(2,31));
}
function zigset(){
// seed generator based on current time
jsr ^= new Date().getTime();
var m1 = 2147483648.0;
var dn = 3.442619855899;
var tn = dn;
var vn = 9.91256303526217e-3;
var q = vn / Math.exp(-0.5 * dn * dn);
kn[0] = Math.floor((dn/q)*m1);
kn[1] = 0;
wn[0] = q / m1;
wn[127] = dn / m1;
fn[0] = 1.0;
fn[127] = Math.exp(-0.5 * dn * dn);
for(var i = 126; i >= 1; i--){
dn = Math.sqrt(-2.0 * Math.log( vn / dn + Math.exp( -0.5 * dn * dn)));
kn[i+1] = Math.floor((dn/tn)*m1);
tn = dn;
fn[i] = Math.exp(-0.5 * dn * dn);
wn[i] = dn / m1;
}
}
zigset();
}
Run Code Online (Sandbox Code Playgroud)
创建一个 Ziggurat.js 文件,然后:
var z = new Ziggurat();
z.nextGaussian();
Run Code Online (Sandbox Code Playgroud)
对我来说,它工作得非常完美,正如我在维基百科中读到的那样,这是一种比 Box-Muller 更有效的算法。