JavaScript Random Number Generation: Complete Guide

Learn how to generate random numbers in JavaScript with Math.random. Practical patterns for random integers, array elements, colors, and dice rolls.

4 min read

Math.random() returns a pseudo-random decimal between 0 (inclusive) and just under 1 (exclusive). Every call produces a different value. It is the foundation for all random number patterns in JavaScript.

javascriptjavascript
console.log(Math.random());
console.log(Math.random());
console.log(Math.random());

Three calls print three different decimals, each somewhere between 0 and 0.999... The values are spread uniformly across that range.

For an overview of all Math object methods, see the JavaScript Math object guide.

Random integers in a range

Math.random alone produces decimals, but most use cases need whole numbers. The pattern is: multiply to scale the range, floor to drop the decimal, then add to shift.

For a random integer between 0 and N (exclusive):

javascriptjavascript
const index = Math.floor(Math.random() * 5);
console.log(index);

This prints 0, 1, 2, 3, or 4. Multiplying by 5 gives a range of 0 to 4.999..., floor drops the decimal to 0 through 4.

For a random integer between min and max inclusive, use the full formula:

javascriptjavascript
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
 
console.log(randomInt(1, 6));
console.log(randomInt(10, 20));

The first prints a die roll (1 through 6). The second prints a number from 10 through 20. The +1 on (max - min + 1) is essential for including the upper bound.

Random array element

Picking a random item from an array combines Math.random with array indexing:

javascriptjavascript
const colors = ["red", "blue", "green", "yellow", "purple"];
 
const randomColor = colors[Math.floor(Math.random() * colors.length)];
 
console.log(randomColor);

Math.random times the array length gives an index within range. Math.floor converts it to a valid integer index. This pattern works for any array, regardless of size or content type.

For shuffling an entire array randomly, use the Fisher-Yates algorithm:

javascriptjavascript
function shuffle(arr) {
  for (let i = arr.length - 1; i > 0; i -= 1) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}
 
const deck = [1, 2, 3, 4, 5];
console.log(shuffle(deck));

Each iteration swaps the current element with a random earlier element. After one pass, the array is uniformly shuffled.

Random boolean and random color

For a coin flip or a random true/false, check if Math.random is above or below 0.5:

javascriptjavascript
const coinFlip = Math.random() < 0.5;
console.log(coinFlip ? "heads" : "tails");

This prints "heads" or "tails" with roughly equal odds, since Math.random() is below 0.5 about half the time and at or above 0.5 the other half.

Generating a random color follows the same scale-and-convert idea, but instead of a boolean it produces a random integer and converts that number into a hex string:

javascriptjavascript
const randomHex = Math.floor(Math.random() * 0xffffff)
  .toString(16)
  .padStart(6, "0");
 
console.log(`#${randomHex}`);

This prints something like #a3f2c1. The expression 0xffffff is 16777215 in hexadecimal notation, which is the highest value for a six-digit hex color.

Math.random vs crypto.getRandomValues

Math.random is fine for games, animations, and random UI behavior. It is not suitable for password generation, authentication tokens, or encryption. For those security-sensitive use cases, use crypto.getRandomValues instead. This method uses the operating system's cryptographic random source:

javascriptjavascript
const array = new Uint32Array(1);
crypto.getRandomValues(array);
 
console.log(array[0]);

This uses the operating system's cryptographic random source and is suitable for security-sensitive applications. The trade-off is that crypto.getRandomValues is slightly slower than Math.random.

Common mistakes

Forgetting the +1 in the integer range formula excludes the upper bound. The expression Math.floor(Math.random() * 6) gives 0 through 5, not 1 through 6. Add 1 after floor when you need the upper bound included.

Expecting Math.random to accept a range argument does not work. Math.random takes no arguments. You must apply the multiplication and floor pattern yourself.

Using Math.random for any security purpose is incorrect. It is a pseudo-random generator that can be predicted with enough effort. For the guide to rounding numbers, you will see how floor and random work together in more patterns.

Rune AI

Rune AI

Key Insights

  • Math.random() returns a decimal between 0 (inclusive) and 1 (exclusive).
  • For a random integer from min to max inclusive: Math.floor(Math.random() * (max - min + 1)) + min.
  • Pick a random array element with arr[Math.floor(Math.random() * arr.length)].
  • Math.random is pseudo-random and not suitable for cryptography.
  • Use crypto.getRandomValues() for security tokens and passwords.
RunePowered by Rune AI

Frequently Asked Questions

Is Math.random() truly random?

No. Math.random uses a pseudo-random number generator. It is random enough for games, animations, and UI behaviors, but not for cryptography. Use crypto.getRandomValues() for security-sensitive randomness.

Can I seed Math.random with a custom starting value?

No. Math.random does not support seeding. If you need reproducible random sequences for testing, use a third-party seeded random library or implement your own generator.

How do I generate a random number between two values?

Use Math.floor(Math.random() * (max - min + 1)) + min for inclusive integer ranges. For decimals between min and max (exclusive), use Math.random() * (max - min) + min.

Conclusion

Math.random is the built-in way to generate pseudo-random numbers in JavaScript. It returns a decimal between 0 and 1, which you scale and shift to fit any range. The most common patterns are random integers with Math.floor, random array elements, and random colors. For security-sensitive randomness, use crypto.getRandomValues instead.