Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a random number focused on center

The simplest way would be to generate two random numbers from 0-50 and add them together.

This gives a distribution biased towards 50, in the same way rolling two dice biases towards 7.

In fact, by using a larger number of "dice" (as @Falco suggests), you can make a closer approximation to a bell-curve:

function weightedRandom(max, numDice) {
    let num = 0;
    for (let i = 0; i < numDice; i++) {
        num += Math.random() * (max/numDice);
    }    
    return num;
}

Weighted random numbers

JSFiddle: http://jsfiddle.net/797qhcza/1/


You have some good answers here that give specific solutions; let me describe for you the general solution. The problem is:

  • I have a source of more-or-less uniformly distributed random numbers between 0 and 1.
  • I wish to produce a sequence of random numbers that follow a different distribution.

The general solution to this problem is to work out the quantile function of your desired distribution, and then apply the quantile function to the output of your uniform source.

The quantile function is the inverse of the integral of your desired distribution function. The distribution function is the function where the area under a portion of the curve is equal to the probability that the randomly-chosen item will be in that portion.

I give an example of how to do so here:

http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/

The code in there is in C#, but the principles apply to any language; it should be straightforward to adapt the solution to JavaScript.


Taking arrays of numbers, etc. isn't efficient. You should take a mapping which takes a random number between 0 to 100 and maps to the distribution you need. So in your case, you could take f(x)=-(1/25)x2+4x to get a distribution with the most values in the middle of your range.

Distribution


I might do something like setup a "chance" for the number to be allowed to go "out of bounds". In this example, a 20% chance the number will be 1-100, otherwise, 40-60:

$(function () {
    $('button').click(function () {
        var outOfBoundsChance = .2;
        var num = 0;
        if (Math.random() <= outOfBoundsChance) {
            num = getRandomInt(1, 100);
        } else {
            num = getRandomInt(40, 60);
        }
        $('#out').text(num);
    });
    
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<button>Generate</button>
<div id="out"></div>

fiddle: http://jsfiddle.net/kbv39s9w/


I needed to solve this problem a few years ago and my solution was easier than any of the other answers.

I generated 3 randoms between the bounds and averaged them. This pulls the result towards the centre but leaves it completely possible to reach the extremities.


It looks stupid but you can use rand twice:

var choice = Math.random() * 3;
var result;

if (choice < 2){
    result = Math.random() * 20 + 40; //you have 2/3 chance to go there
}
else {
    result = Math.random() * 100 + 1;
}

Sure it is possible. Make a random 1-100. If the number is <30 then generate number in range 1-100 if not generate in range 40-60.