Different probability for ranges of random numbers

前端 未结 2 1760
感情败类
感情败类 2021-01-03 05:30

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 retur

相关标签:
2条回答
  • 2021-01-03 06:09

    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.

    0 讨论(0)
  • 2021-01-03 06:30

    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>
    
    0 讨论(0)
提交回复
热议问题