Solución:
Dado que este es el primer resultado de Google para “js gaussian random” en mi experiencia, siento la obligación de dar una respuesta real a esa consulta.
La transformada de Box-Muller convierte dos variantes uniformes independientes en (0, 1) en dos variantes gaussianas estándar (media 0, varianza 1). Esto probablemente no sea muy eficaz debido a la sqrt
, log
, y cos
llamadas, pero este método es superior a los enfoques del teorema del límite central (sumando N variables uniformes) porque no restringe la salida al rango acotado (-N / 2, N / 2). También es muy simple:
// 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 );
}
Distribución normal entre 0 y 1
Basado en la respuesta de Maxwell, este código usa la transformada Box-Muller para darle una distribución normal entre 0 y 1 inclusive. Simplemente vuelve a muestrear los valores si está a más de 3.6 desviaciones estándar (menos del 0.02% de probabilidad).
function randn_bm() {
let 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;
}
Visualizaciones
n = 100
n = 10,000
n = 10,000,000
Distribución normal con mínimo, máximo, sesgo
Esta versión le permite dar un factor mínimo, máximo y de sesgo. Vea mis ejemplos de uso en la parte inferior.
function randn_bm(min, max, skew) {
let 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;
}
randn_bm(-500, 1000, 1);
randn_bm(10, 20, 0.25);
randn_bm(10, 20, 3);
Aquí está el JSFiddle para estas capturas de pantalla: https://jsfiddle.net/2uc346hp/
Quiero saber si la función de JavaScript Math.random es una distribución normal o no
Javascript Math.random es no a Distribución normal (curva de campana gaussiana). De ES 2015, 20.2.2.27 “Devuelve un valor numérico con signo positivo, mayor o igual a 0 pero menor que 1, elegido aleatoriamente o pseudoaleatoriamente con una distribución aproximadamente uniforme sobre ese rango, utilizando un algoritmo o estrategia dependiente de la implementación. la función no acepta argumentos “. Entonces, la colección proporcionada cuando n es lo suficientemente alta obtendremos una distribución aproximadamente uniforme. Todos los valores en el intervalo tendrán la misma probabilidad de aparición (línea recta paralela al eje x, que denota un número entre 0.0 y 1.0).
¿Cómo puedo obtener números de distribución normal?
Hay varias formas de obtener una colección de números con una distribución normal. Como respondió Maxwell Collard, la transformada Box-Muller transforma la distribución uniforme en distribución normal (el código se puede encontrar en la respuesta de Maxwell Collard).
Una respuesta a otra respuesta de stackoverflow a una pregunta tiene una respuesta con otra distribución uniforme a los algoritmos de distribución normal. Tales como: Zigurat, Proporción de uniformes, Invertir el CDF Además, una de las respuestas dice que: dice:
El algoritmo Ziggurat es bastante eficiente para esto, aunque la transformación Box-Muller es más fácil de implementar desde cero (y no muy lenta).
Y finalmente
Quiero reconstruir una máquina Schmidt (físico alemán), la máquina produce números aleatorios de 0 o 1 y tienen que tener una distribución normal para poder dibujarlos en la curva de campana gaussiana.
Cuando tenemos solo dos valores (0 o 1), la curva gaussiana se ve igual que una distribución uniforme con 2 valores posibles. Es por eso que un simple
function randomZero_One(){
return Math.round(Math.random());
}
bastaría. Devolvería pseudoaleatoriamente con valores de probabilidad aproximadamente iguales 0 y 1.