Categories
integer javascript random

Generating random whole numbers in JavaScript in a specific range

2369

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?

5

  • 2

    here is a useful gist: gist.github.com/kerimdzhanov/7529623

    – Dan K.K.

    Nov 18, 2013 at 15:36

  • 15

    As a side note: for those using npm and looking for a quick, reliable and ready-made solution there’s lodash.random that can be easily required with a super small footprint (it will import just the method itself and not the whole lodash).

    – Aurelio

    Sep 8, 2015 at 16:10

  • if it need to be crypto secure developer.mozilla.org/en-US/docs/Web/API/RandomSource/…

    – happy

    Dec 12, 2015 at 23:46

  • Can you be explicit in the question about the number range? In particular, zero. What about negative numbers? (Texts that exclude zero from the natural numbers sometimes refer to the natural numbers together with zero as the whole numbers”). (But without “Edit:”, “Update:”, or similar – the question should appear as if it was written today.)

    Apr 29 at 11:04


  • 2

    Many answers here answer some different question (they are not real answers). It is like some users only read “Generating random whole numbers” and never get to the “in a specific range” part (or even the body with the [4; 8] example).

    Apr 29 at 13:44


4575

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... min+2 ... 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.

34

  • 17

    It’s only doing that because it’s calling floor, which rounds down.

    Oct 6, 2009 at 20:17

  • 6

    @thezachperson31 You could use round, but then both, min and max only had half the chance to roll like the other numbers do. You could also substract one and take ceil. This however leaves the max number with a minimal less chance to roll due to the [0,1) Interval.

    – Christoph

    Dec 22, 2012 at 9:18

  • 19

    I’ve created a JSFiddle if anyone wants to test the distribution of this method: jsfiddle.net/F9UTG/1

    – ahren

    Jun 5, 2013 at 13:56


  • 9

    @JackFrost yeah, that’s right. You’re not dumb, you’re just learning 🙂

    Jan 27, 2016 at 14:19

  • 4

    This question is old, but understanding this answer took me way too much time O.o, I think expanding math.random on next JavaScript version would be kind of useful

    Mar 8, 2016 at 16:09

608

var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;

5

  • 32

    I know this is a VERY old answer, but using (Math.random() * (maximum - minimum + 1) ) << 0 is faster.

    Mar 1, 2015 at 5:05

  • 22

    @IsmaelMiguel Using binary operators (x << 0, x | 0, ~~x) instead of Math.floor() converts x into a two-complement with much smaller range than Number.MAX_SAFE_INTEGER (2³²⁻¹ vs. 2⁵³), thus you have to use it with caution!

    – le_m

    Jun 6, 2016 at 1:49

  • @IsmaelMiguel Yo I just tried your method in the console and randomly got a negative value! Math.randRange = (minimum, maximum) => (Math.random() * (maximum – minimum + 1) ) << 0 Math.randRange(2,657348096152) -1407373159

    Feb 13, 2019 at 11:00

  • @bluejayke Because 657348096152 (1001100100001100111111111111000010011000 in binary) has 40 bits, while bitwise arithmetics use 32 bits. If you do 657348096152|0 you get 218099864 (1100111111111111000010011000 in binary).

    Feb 13, 2019 at 19:49

  • 3

    This is a smart answer. Making the range internally [min, max+1) actually achieves the desired result of [min, max] being both inclusive. Thank you! 🙂

    – Mladen B.

    May 15, 2019 at 6:18

225

Math.random()

Returns an integer random number between min (included) and max (included):

function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Or any random number between min (included) and max (not included):

function randomNumber(min, max) {
  return Math.random() * (max - min) + min;
}

Useful examples (integers):

// 0 -> 10
Math.floor(Math.random() * 11);

// 1 -> 10
Math.floor(Math.random() * 10) + 1;

// 5 -> 20
Math.floor(Math.random() * 16) + 5;

// -10 -> (-2)
Math.floor(Math.random() * 9) - 10;

** And always nice to be reminded (Mozilla):

Math.random() does not provide cryptographically secure random
numbers. Do not use them for anything related to security. Use the Web
Crypto API instead, and more precisely the
window.crypto.getRandomValues() method.

1

  • 2

    If you take Math.ceil, then +1 can be spared

    Nov 13, 2020 at 14:12