javascript - Javascript pseudo-random - Javascript random number

Creating Javascript Random Numbers with Math.random()

Javascript is a full-featured programming language, able to make complex mathematical calculations quickly and accurately. The Javascript standard makes it easier to do these calculations with the Math object.

One of the most common ways programmers use the Math object is to create random numbers. Randomness is used programmatically in art, science, and gaming. Whether you’re simulating the stroke of a sable paintbrush, running a controlled medical trial, building an online casino, or encrypting anything, you need random numbers.

Creating Javascript random numbers is different from simply assigning a number to a variable within a program — some interesting actions go on behind the scenes.

What is Randomness in Javascript?

It is impossible in computing to generate completely random numbers. This is because every calculation inside a computer has a logical basis of cause and effect, while random events don’t follow that logic.

Computers are not capable of creating something truly random. True randomness is only possible through a source of external data that a computer cannot generate, such as the movement of many lava lamps at once (which has been used as an unbreakable random encryption in the real world), meteographic noise, or nuclear decay.

The solution that Javascript, and other programming languages, use to implement randomness is “pseudo-random” number generation. Javascript random numbers start from a hidden internal value called a “seed.” The seed is a starting point for a hidden sequence of numbers that are uniformly distributed throughout their possible range.

Developers cannot change Javascript’s pseudo-random seed or the distribution of values in its generated pseudo-random sequences. Different Javascript implementations and different browsers often start with different seeds. Do not assume that different browsers, or even different computers, will always use the same seed.

Javascript random numbers are not safe for use in cryptography because deciphering the seed could lead to decryption of the hidden number sequence. Some functions exist to create cryptographically secure pseudo-random numbers in Javascript, but they are not supported by older browsers.

In this blog post, we’ll first cover the canonical methods of creating Javascript random numbers. Then we’ll move onto ways of obtaining higher-quality random data; your needs will determine the worthwhile effort.

Generating Javascript Random Numbers

Javascript creates pseudo-random numbers with the function Math.random(). This function takes no parameters and creates a random decimal number between 0 and 1. The returned value may be 0, but it will never be 1.

let value1 = Math.random();

You can use Math.random() to create whole numbers (integers) or numbers with decimals (floating point numbers). Since Math.random() creates floating point numbers by default, you can create a random floating point number simply by multiplying your maximum acceptable value by the result from Math.random(). Therefore, to create a pseudo-random number between 0 and 2.5:

let value2 = Math.random() * 2.5;

Creating a pseudo-random integer is a little more difficult; you must use the function Math.floor() to round your computed value down to the nearest integer. So, to create a random number between 0 and 10:

let value3 = Math.floor(Math.random() * 10);

Generating Javascript Random Numbers More Easily

Math.random() is a useful function, but on its own it doesn’t give programmers an easy way to generate pseudo-random numbers for specific conditions. There may be a need to generate random numbers in a specific range that doesn’t start with 0, for example.

Fortunately, there are simple Javascript functions that programmers can create to make pseudo-random numbers more manageable. The rest of this section will show you how to create those functions, then put them all together into a single pseudo-random number generator.

Integer Pseudo-Random Numbers Across A Range

In the previous examples, Math.random() could never create a number at the very top of a specified range. If you wanted a number between 0 and 5, for example, you could get 0-4, but never 5. The solution to this problem, if you’re creating an integer, is adding 1 to the result.

// Generate a number between 0 and 10, including 10
function generateRandomInteger(max) {
    return Math.floor(Math.random() * max) + 1;
}

let value4 = generateRandomInteger(10);

Since floating point numbers in Javascript go out to many decimal places, there isn’t a simple one-number solution to include the maximum possible floating point number in your range unless you want to make shaky assumptions and type a lot of zeroes. Instead, you can use some simple math that also works with integers to get pseudo-random numbers all across your range.

// Generate a random number between 2 and 10, including both 2 and 10
function generateRandomIntegerInRange(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

let value5 = generateRandomIntegerInRange(2, 10);

Floating-Point Pseudo-Random Numbers Across A Range

A function that does this for floating point numbers would look almost identical, except that it wouldn’t use Math.floor():

// Generate a random number between 2.5 and 10.75, including both 2.5 and 10.75
function generateRandomFloatInRange(min, max) {
    return (Math.random() * (max - min + 1)) + min;
}

let value6 = generateRandomFloatInRange(2.5, 10.75);

Floating point numbers remain a little tricky here because Math.random() by default generates the maximum number of decimal places the Javascript implementation allows. In most circumstances, you probably want to cap your decimal places at 3 or 4 instead of reading the 10 or more that Math.random() usually creates.

Floating-Point Pseudo-Random Numbers With Specific Decimal Places

The toFixed() function formats a number with the number of decimal places you specify. To make sure that you don’t accidentally create a string in some Javascript implementations, it’s best to always chain toFixed() with the Number.parseFloat() function.

// Generate a random number between 2.5 and 10.75, including both 2.5 and 10.75, and specifying 2 decimal places
function generateRandomDecimalInRangeFormatted(min, max, places) {
    let value = (Math.random() * (max - min + 1)) + min;
    return Number.parseFloat(value).toFixed(places);
}

let value7 = generateRandomDecimalInRangeFormatted(2.5, 10.75, 2);

Putting It All Together

Putting all of this together, a Javascript pseudo-random number generator that can create integers or floating point numbers with any number of decimal places could look like this. (Note that this implementation also includes error checking for the parameters.)

function generateRandomNumbers(min, max, places) {
    // If both the minimum and maximum values are integers, return a random integer. Don't let the user specify any decimal places.
    if (Number.isInteger(min) && Number.isInteger(max)) {
        if (places !== undefined) {
            new Error("Cannot specify decimal places with integers.");
        }
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    // Otherwise, return a random floating point number with specified decimal places.
    else {

        // Make sure the minimum value is a number.
        if (Number.isNaN(Number.parseFloat(min))) {
            new Error("Minimum value is not a number.");
        }

        // Make sure the maximum value is a number.
        if (Number.isNaN(Number.parseFloat(max))) {
            new Error("Maximum value is not a number.");
        }

        // Make sure the decimal places value is a non-negative number greater than 0.
        if (Number.isInteger(places) === false) {
            new Error("Number of decimal places is not a number.");

} if (places <= 0) { new Error("Number of decimal places must be at least 1."); } // Generate the floating point number. let value = (Math.random() * (max - min + 1)) + min; return Number.parseFloat(value).toFixed(places); } }

Other Pseudo-Random Number Generators

Crypto.getRandomValues()

Cryptographically strong pseudo-random values are available on all web browsers that support Crypto.getRandomValues(). Implementations vary across user agents, but all are required to use a seed with enough entropy. To fill an array with results try:

let array = new Uint32Array(10);
window.crypto.getRandomValues(array);

The Middle Square Method

Invented by John von Neumann around 1946, the Middle Square Method (MSM) generates a pseudo-random number sequence by extracting the middle digits from a squared number.

let seed = 42;
function middleSquareMethod() {
    let result = (seed*seed).toString().padStart(4,"0").slice(1,3);

    // Pad with zeros as necessary, then extract the middle value.
    seed = parseInt(result);
    return parseInt(result); // return 2-digit pseudo-random number
}

Beware of certain seed values, like 25, which have a shorter cycle or cause the algorithm to repeat one value indefinitely.

Linear Congruential Generator

Invented around 1958 by Thomson & Rotenberg, the Linear Congruential Generator (LGC) algorithm is perhaps the oldest-known. It’s fast, and when care is taken with the initial values, quite adequate.

let increment = 1013904223;
let modulus = 232;
let multiplier = 1664525; // see Numerical Recipes for initial values
let seed;

function linearCongruentialGenerator() {
    X = ( multiplier * X + increment ) % modulus;
    return seed;
}

Xorshift family of pseudo-random number generators

Xorshift or “shift-register generators” are a family of pseudorandom number generators that were discovered by George Marsaglia in 2003. Among the fastest PRNGs, they use bitwise operations to deliver a high-quality sequence.

let seed;

function xorShift() {
    seed ^= seed << 13; seed ^= seed >> 17; seed ^= seed << 5;
    return seed;
}

The xorshift variants —  xorwow, xorshift+, xoshiro, xoroshiro, xoshiro256*, xoshiro256+ — each provide a different method; research into the suitability of each of these for your needs is time well spent.

True Random Numbers

As mentioned above, true random numbers must spring for a source outside computers without hardware dedicated to this purpose. For needs that require truly random cryptographically appropriate random numbers use one of the following external sources via their public APIs:

  • random.org samples atmospheric noise and provides several data sources: integer, sequence, set, gaussian, float, and raw random data.
  • The Australian National University (ANU) Quantum Optics Group’s Quantum RNG derives random numbers by measuring the quantum fluctuations of a vacuum. Additionally, you can see and hear random number sequences.
  • The Ruđer Bošković Institute Quantum Random Bit Generator Service harvests randomness from the quantum process of photonic emission in semiconductors, made available through many libraries for programming languages and other methods.
  • The Taiyuan University of Technology Physical Random Number Generator Service publishes random numbers sourced from a chaotic laser.

Conclusion

Javascript random numbers are more complex to generate than they may first appear. They are a basic Javascript concept but require some additional conceptual knowledge when generating for specific circumstances. Here we’ve covered various techniques to obtain pseudo-random numbers with Math.Random().

Enroll in our Intro to Programming Nanodegree Program today to learn more about Javascript random number generation and other programming concepts.

Start Learning

Jessica Reuter Castrogiovanni
Jessica Reuter Castrogiovanni