﻿ Random Numbers in JavaScript

# Random Numbers in JavaScript

by kirupa with code by Scott Ruttencutter   |   filed under JavaScript 101

Learn how to generate a range of random numbers that fall not only within an upper and lower range you specify, but the frequency that each number appears is fair and balanced! ⚖️

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)
let foo = Math.floor(Math.random() * 11);
console.log(foo);

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

// Random number between 5 and 25 (inclusive)
let 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) {
let 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)
let foo = getRandomNumber(0, 10);
console.log(foo);

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

// Random number between 5 and 25 (inclusive)
let 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.

Got a question or just want to chat? Comment below or drop by our forums (they are actually the same thing!) where a bunch of the friendliest people you'll ever run into will be happy to help you out!  