Random number generator with non-equal distribution of numbers

478 views Asked by At

I know that I can use

var rolls = [];
for (var i=0; i<100; i++) {
  rolls.push(Math.floor(6 * Math.random()) + 1);
}

to get 100 rolls with a single die.

But what if it is a magic die, where each number doesn't show up equally?

So instead of each number showing up 1/6th of the time, the numbers 1-4 each shows up 10% of the time whereas 5 shows up 20% of the time and the remaining 6 shows up 100%-20%-4*10% = 40% of the time.

How do you make such a random number generator where the distribution can easily be adjusted?

2

There are 2 answers

0
Nina Scholz On BEST ANSWER

You could use an array with probabilities and check and count against a random value.

This function sets first the return value to the last possible index and iterates until the rest of the random value is smaller than the actual probability.

The probabilities have to sum to one.

function getRandomIndexByProbability(probabilities) {
    var r = Math.random(),
        index = probabilities.length - 1;

    probabilities.some(function (probability, i) {
        if (r < probability) {
            index = i;
            return true;
        }
        r -= probability;
    });
    return index;
}

var i,
    probabilities = [0.1, 0.1, 0.1, 0.1, 0.2, 0.4],
    count = {},
    index;

probabilities.forEach(function (_, i) { count[i + 1] = 0; });

for (i = 0; i < 1e6; i++) {
    index = getRandomIndexByProbability(probabilities);
    count[index + 1]++;
}

console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0
Konrad Lalik On

You can create a collection with desired distribution e.g

var distribution = [1,1,1,2,2,3];
var randomItem = new Random().Next(distribution.Length);
if(randomItem == 1) 
{ 
   //do something with with probability 50%
}
else if (randomItem == 2)
{
   //do something with with probability 33%
}
else if (randomItem == 3)
{
   //do something with with probability 17%
}

Now you can add code that should be executed for each case