Generating random whole numbers in JavaScript in a specific range

integer, javascript, random

Solution

There are some examples on the Mozilla Developer Network page:

/**
 * Returns a random number between min (inclusive) and max (exclusive)
 */
function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}

/**
 * Returns a random integer between min (inclusive) and max (inclusive).
 * The value is no lower than min (or the next integer greater than min
 * if min isn't an integer) and no greater than max (or the next integer
 * lower than max if max isn't an integer).
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

Here's the logic behind it. It's a simple rule of three:

`Math.random()` returns a `Number` between 0 (inclusive) and 1 (exclusive). So we have an interval like this:

[0 .................................... 1)

Now, we'd like a number between `min` (inclusive) and `max` (exclusive):

[0 .................................... 1)
[min .................................. max)

We can use the `Math.random` to get the correspondent in the [min, max) interval. But, first we should factor a little bit the problem by subtracting `min` from the second interval:

[0 .................................... 1)
[min - min ............................ max - min)

This gives:

[0 .................................... 1)
[0 .................................... max - min)

We may now apply `Math.random` and then calculate the correspondent. Let's choose a random number:

                Math.random()
                    |
[0 .................................... 1)
[0 .................................... max - min)
                    |
                    x (what we need)

So, in order to find `x`, we would do:

x = Math.random() * (max - min);

Don't forget to add `min` back, so that we get a number in the [min, max) interval:

x = Math.random() * (max - min) + min;

That was the first function from MDN. The second one, returns an integer between `min` and `max`, both inclusive.

Now for getting integers, you could use `round`, `ceil` or `floor`.

You could use `Math.round(Math.random() * (max - min)) + min`, this however gives a non-even distribution. Both, `min` and `max` only have approximately half the chance to roll:

min...min+0.5...min+1...min+1.5   ...    max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘   ← Math.round()
   min          min+1                          max

With `max` excluded from the interval, it has an even less chance to roll than `min`.

With `Math.floor(Math.random() * (max - min +1)) + min` you have a perfectly even distribution.

 min...  min+1...    ...      max-1... max....   (max+1 is excluded from interval)
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘   ← Math.floor()
   min     min+1               max-1    max

You can't use `ceil()` and `-1` in that equation because `max` now had a slightly less chance to roll, but you can roll the (unwanted) `min-1` result too.

Problem

How can I generate random whole numbers between two specified variables in JavaScript, e.g. `x = 4` and `y = 8` would output any of `4, 5, 6, 7, 8`?

Original source

Related problems