Different probability for ranges of random numbers

倖福魔咒の 提交于 2019-12-30 05:12:05

问题


I'm looking for the best way of implementing random number generator, that will allow me to have control over probability from what range the generated number will be returned. To visualize what I'm trying to achieve I have a picture :

So to summarize : Let's say that my range is 400. At the beginning I'd like to have 5% probability of getting number 0-20. But at some moment in time I'd like to have this probability increased up to 50%. Hope you get the idea.


回答1:


Hmm, working on your original I had a pretty simple algorithm to generate ranges in an array in the appropriate proportion, then randomly select a range and generate a random number within that range. No doubt it can be optimised if necessary, but it works for me.

It looks like a lot of code, but 3/4 of it is comments, test data and function, the actual randomRange function is only 17 lines of code.

<script type="text/javascript">

function randomRange(dataArray) {

  // Helper function
  function getRandomInRange(s, f) {
    return (Math.random() * (f-s+1) | 0) + s
  }

  // Generate new data array based on probability
  var i, j = dataArray.length;
  var oArray = [];
  var o;
  while (j--) {
    o = dataArray[j];

    // Make sure probability is an integer
    for (i=0, iLen=o.probability|0; i<iLen; i++) {  
      oArray.push([o.rangeStart, o.rangeEnd]);
    }
  }

  // Randomly select a range from new data array and
  // generate a random number in that range
  var oEnd = oArray.length;
  var range = oArray[getRandomInRange(0, oArray.length - 1)]; 
  return getRandomInRange(range[0], range[1]);
}

// Test data set. Probability just has to be
// representative, so 50/50 === 1/1
var dataArray = [
  {
    rangeStart: 0, 
    rangeEnd  : 20,
    probability: 1
  },
  {
    rangeStart: 21, 
    rangeEnd  : 400,
    probability: 1
  }
];

// Test function to show range and number is randomly
// selected for given probability
function testIt() {
  var el0 = document.getElementById('div0');
  var el1 = document.getElementById('div1');
  function run() {
    var n = randomRange(dataArray);
    if (n <= 20) {
      el0.innerHTML += '*';
    } else {
      el1.innerHTML += '*';
    }
  }
  setInterval(run, 500);
}


</script>

<button onclick="testIt();">Generate random number</button>

<div>Numbers 0 - 20</div>
<div id="div0"></div>
<div>Numbers 21 - 400</div>
<div id="div1"></div>



回答2:


It sounds to me like what you're looking for is a way to generate numbers on a normal (or Gaussian) distribution (take a look at the Wikipedia page if you don't know what that means).

The Box-Muller transformation can be used to generate pairs of normally distributed numbers.

Here is a c++ implementation of the polar form of the Box-Muller transformation that shouldn't be hard to translate to javascript.

// Return a real number from a normal (Gaussian) distribution with given
// mean and standard deviation by polar form of Box-Muller transformation
double x, y, r;
do
{
    x = 2.0 * rand() - 1.0;
    y = 2.0 * rand() - 1.0;
    r = x * x + y * y;
}
while ( r >= 1.0 || r == 0.0 );
double s = sqrt( -2.0 * log(r) / r );
return mean + x * s * stddev;

Where mean is the mean of the normal distribution and stddev is the Standard Deviation of the distribution. This code is from a MersesenneTwister C++ class that I've been using recently that you can find on Rick Wagner's page. You can find some more useful information about the Box-Muller transformation on this page.



来源:https://stackoverflow.com/questions/6025252/different-probability-for-ranges-of-random-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!