Say, if I wanted to generate an unbiased random number between min
and max
, I'd do:
var rand = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
But what if I want to generate a random number between min
and max
but more biased towards a value N
between min
and max
to a degree D
? It's best to illustrate it with a probability curve:
Here is one way:
Ie., in 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
The mix factor can be reduced with a secondary factor to set how much it should influence (ie. mix * factor
where factor is [0, 1]).
This will plot a biased random range. The upper band has 1 as influence, the bottom 0.75 influence. Bias is here set to be at 2/3 position in the range. The bottom band is without (deliberate) bias for comparison.
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>
Very nice. Thanks for the demo.
@c00000fd no problem! I forgot to mention that the bias can be more influential by going above 1 and clamp down the result in the mix. But you probably already see this. Good luck with your project!
What happens if I want to have value of 1 or 0, but i want the outcome to be 67% 1s?