Generating Random Numbers in JavaScript

by kirupa with code by Scott Ruttencutter   |   1 April 2018

  Have questions? Discuss this HTML5 / JavaScript tutorial with others on the forums.

For many situations ranging from coin toss operations to procedural animations, you will want to work with numbers whose values are a bit unpredictable. You will want to work with numbers that are random. Generating a random number is easy. It is built-in to JavaScript and exposed via the infamous Math.random() function. Now, if this function already exists, what are we still doing here? Well, using the function is only part of being able to generate a random number. For most real-life situations, we don't want just any random number. We will want a specific type of random number - one that falls within a range that we define. There are some subtle gotchas with that, and that's what the rest of these sections will explore.

Onwards!

Just Show Me the Code

Before I dive into the details, if all you want is the code for generating a random whole number within a set range, use Math.random() with the following formula:

Math.floor(Math.random() * (1 + High - Low)) + Low

The value for High is the largest random number you would like to generate. The value for low is the smallest random number you would like to generate instead. When you run this code, what you will get is a number that randomly falls somewhere between the bounds specified by High and Low.

Here are some examples:

// Random number between 0 and 10 (inclusive)
var foo = Math.floor(Math.random() * 11);
console.log(foo);

// Random number between 0 and 100 (inclusive)
var bar = Math.floor(Math.random() * 101);
console.log(bar);

// Random number between 5 and 25 (inclusive)
var zorb = Math.floor(Math.random() * 21) + 5;
console.log(zorb);

To make things simple, here is a function you can use instead:

function getRandomNumber(low, high) {
  var r = Math.floor(Math.random() * (high - low + 1)) + low;
  return r;
}

Just call getRandomNumber and pass in the lower and upper bound as arguments:

// Random number between 0 and 10 (inclusive)
var foo = getRandomNumber(0, 10);
console.log(foo);

// Random number between 0 and 100 (inclusive)
var bar = getRandomNumber(0, 100);
console.log(bar);

// Random number between 5 and 25 (inclusive)
var zorb = getRandomNumber(5, 25);
console.log(zorb);

That's all there is to generating a random number that falls within a range that you specify.

The Addition of 1 Explained

In JavaScript, Math.random() returns a number greater than or equal to 0 but less than 1:

Another way of stating that is (0 <=  n < 1) where n is the number you are looking for. This inability for Math.random to get really REALLY close to 1 but never quite getting there is largely why getting a random number between a range of numbers is so...inelegant:

Math.floor(Math.random() * (1 + High - Low)) + Low

Looking at our approach a bit further, let's start with the biggest oddity, the addition of the 1. Here is why we include it. We have already stated many times that the Math.random() function will never return a 1 as its value. It will return something close like .9999999, but it won't ever be a 1. We also want a round number that doesn't include decimals. There are several approaches for rounding a number, but we are rounding the output by Math.floor where we round down to the nearest integer. This rounding down is the problem.

If we did not add the 1, because of how Math.floor works, it will never get the maximum possible answer when we multiply the result of High - Low by Math.random(). This probably doesn't make a lot of sense, so let's look at an example where attempt to get a random number without adding the 1.

What we want to do is generate a random number between 10 and 50. Ignoring the 1, this is what the expression will look like:

Math.floor(Math.random() * 40) + 10

The Math.random() * 40 will never return a 40 because that would require Math.random() to return a 1...which it can't. Let's be optimistic and say that Math.random() returns a .9999, and we multiply that value by 40. The value that gets returned will be 39.996. Guess what Math.floor of 39.996 is going to be? It is going to be 39! When this 39 gets added to 10, you get a value of 49. You have no conceivable way of getting an answer of 50 which is the high number in your range of values. The only solution is to add a 1 to the operation:

Math.floor(Math.random() * 41) + 10

Once you do that, you will be able to generate all numbers within the range of your high and low numbers, 10 and 50 respectively, with equal frequency.

Conclusion

Generating random numbers properly is a challenging problem. It seems really simple, but getting the range of numbers not only correct but also occurring with equal frequency is where the challenges happen. As long as you are aware of the limitations of the various rounding methods, you can replace Math.floor with Math.ceil or, if you are really daring, Math.round.

If you have a question about this or any other topic, the easiest thing is to drop by our forums where a bunch of the friendliest people you'll ever run into will be happy to help you out!

THE KIRUPA NEWSLETTER

Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!

( View past issues for an idea of what you've been missing out on all this time! )

GOT A QUESTION?

HOT FORUM TOPICS

Serving you freshly baked content since 1998!

Killer hosting by (mt) mediatemple

Facebook Twitter Youtube Pinterest Instagram Github
BACK TO TOP
new books - yay!!!