Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

javascript - How to generate random numbers biased towards one value in a range?

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:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is one way:

  • Get a random number in the min-max range
  • Get a random normalized mix value
  • Mix random with bias based on random mix

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]).

Demo

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...