valores repetir para numeros numero generar entero codigo aleatorios aleatorio javascript algorithm math probability

javascript - repetir - ¿Cómo generar números aleatorios sesgados hacia un valor en un rango?



numeros aleatorios en javascript sin repetir (4)

Por ejemplo, si quisiera generar un número aleatorio imparcial entre el min y el max , lo haría:

var rand = function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; };

Pero, ¿qué pasa si quiero generar un número aleatorio entre min y max pero más sesgado hacia un valor N entre min y max hasta un grado D ? Lo mejor es ilustrarlo con una curva de probabilidad:


Aquí hay una forma:

  • Consigue un número aleatorio en el rango min-max
  • Obtener un valor de mezcla normalizada al azar
  • Mezcla aleatoria con sesgo basado en mezcla aleatoria

Es decir, en pseudo

Variables: min = 0 max = 100 bias = 67 (N) influence = 1 (D) [0.0, 1.0] Formula: rnd = random() x (max - min) + min mix = random() x influence value = rnd x (1 - mix) + bias x mix

El factor de mezcla se puede reducir con un factor secundario para establecer cuánto debe influir (es decir, mix * factor donde el factor es [0, 1]).

Manifestación

Esto trazará un rango aleatorio sesgado. La banda superior tiene 1 como influencia, la influencia de 0.75 inferior. El sesgo se establece aquí para estar en la posición 2/3 en el rango. La banda inferior es sin sesgo (deliberado) para la comparación.

var ctx = document.querySelector("canvas").getContext("2d"); ctx.fillStyle = "red"; ctx.fillRect(399,0,2,110); // draw bias target ctx.fillStyle = "rgba(0,0,0,0.07)"; function getRndBias(min, max, bias, influence) { var rnd = Math.random() * (max - min) + min, // random in range mix = Math.random() * influence; // random mixer return rnd * (1 - mix) + bias * mix; // mix full range and bias } // plot biased result (function loop() { for(var i = 0; i < 5; i++) { // just sub-frames (speedier plot) ctx.fillRect( getRndBias(0, 600, 400, 1.00), 4, 2, 50); ctx.fillRect( getRndBias(0, 600, 400, 0.75), 55, 2, 50); ctx.fillRect( Math.random() * 600 ,115, 2, 35); } requestAnimationFrame(loop); })();

<canvas width=600></canvas>


Diga cuándo usa Math.floor(Math.random() * (max - min + 1)) + min; , en realidad estás creando una distribución uniforme. Para obtener la distribución de datos en su gráfico, lo que necesita es una distribución con asimetría no cero.

Existen diferentes técnicas para obtener ese tipo de distribuciones. Aquí hay un example de la distribución beta que se encuentra en .

Aquí está el ejemplo resumido del enlace:

unif = Math.random() // The original uniform distribution.

Y podemos transferirlo a la distribución beta haciendo

beta = sin(unif*pi/2)^2 // The standard beta distribution

Para obtener la asimetría que se muestra en su gráfico,

beta_right = (beta > 0.5) ? 2*beta-1 : 2*(1-beta)-1;

Puede cambiar el valor 1 a cualquier otro para que se desvíe a otro valor.


Diversión: utiliza la imagen como función de densidad. Muestra píxeles aleatorios hasta obtener uno negro, luego toma la coordenada x.

Código:

getPixels = require("get-pixels"); // npm install get-pixels getPixels("distribution.png", function(err, pixels) { var height, r, s, width, x, y; if (err) { return; } width = pixels.shape[0]; height = pixels.shape[1]; while (pixels.get(x, y, 0) !== 0) { r = Math.random(); s = Math.random(); x = Math.floor(r * width); y = Math.floor(s * height); } return console.log(r); });

Ejemplo de salida:

0.7892316638026386 0.8595335511490703 0.5459279934875667 0.9044852438382804 0.35129814594984055 0.5352215224411339 0.8271261665504426 0.4871773284394294 0.8202084102667868 0.39301465335302055

Escala al gusto.


Solo por diversión, aquí hay una versión que se basa en la en.wikipedia.org/wiki/Gaussian_function , como se menciona en el comentario de SpiderPig a su pregunta. La función gaussiana se aplica a un número aleatorio entre 1 y 100, donde la altura de la campana indica qué tan cerca estará el valor final de N Interpreté que el grado D significa la probabilidad de que el valor final esté cerca de N , por lo que D corresponde al ancho de la campana: cuanto más pequeña es D , menos probable es el sesgo. Claramente, el ejemplo podría ser calibrado aún más.

(Copié el método de lienzo de Ken Fyrstenberg para demostrar la función).

function randBias(min, max, N, D) { var a = 1, b = 50, c = D; var influence = Math.floor(Math.random() * (101)), x = Math.floor(Math.random() * (max - min + 1)) + min; return x > N ? x + Math.floor(gauss(influence) * (N - x)) : x - Math.floor(gauss(influence) * (x - N)); function gauss(x) { return a * Math.exp(-(x - b) * (x - b) / (2 * c * c)); } } var ctx = document.querySelector("canvas").getContext("2d"); ctx.fillStyle = "red"; ctx.fillRect(399, 0, 2, 110); ctx.fillStyle = "rgba(0,0,0,0.07)"; (function loop() { for (var i = 0; i < 5; i++) { ctx.fillRect(randBias(0, 600, 400, 50), 4, 2, 50); ctx.fillRect(randBias(0, 600, 400, 10), 55, 2, 50); ctx.fillRect(Math.random() * 600, 115, 2, 35); } requestAnimationFrame(loop); })();

<canvas width=600></canvas>