Menu - Top - Home - Donate to Me

Random Number Generator Recommendations for Applications

Peter Occil

Begun on Mar. 5, 2016; last updated on Feb. 20, 2018.

Most apps that use random numbers care about either unpredictability or speed/high quality.

Introduction and Summary

As I see it, there are two kinds of random number generators (RNGs) needed by most applications, namely—

This document covers:

This document does not cover:

The following table summarizes the kinds of RNGs covered in this document:

Kind of RNG When to Use This RNG Examples
Unpredictable-Random In information security cases, or when speed is not a concern. /dev/urandom, BCryptGenRandom
Statistical-Random When information security is not a concern, but speed is. See also "Shuffling". xoroshiro128+, xorshift128+
Seeded PRNG When generating reproducible results in a way not practical otherwise. Statistical-random quality PRNG with custom seed



The following definitions are helpful in better understanding this document.

Unpredictable-Random Generators

Unpredictable-random implementations (also known as "cryptographically strong" or "cryptographically secure" RNGs) seek to generate random numbers that are cost-prohibitive to predict. Such implementations are indispensable in information security contexts, such as—

They are also useful in cases where the application generates random numbers so infrequently that the RNG's speed is not a concern.

An unpredictable-random implementation ultimately relies on one or more nondeterministic sources (sources that don't always return the same output for the same input) for random number generation. Sources that are reasonably fast for most applications (for instance, by producing very many random bits per second), especially sources implemented in hardware, are highly advantageous here, since an implementation for which such sources are available can rely less on PRNGs, which are deterministic and benefit from reseeding as explained later.


An unpredictable-random implementation generates uniformly distributed random bits such that it would be at least cost-prohibitive for an outside party to guess either prior or future unseen bits of the random sequence correctly with more than a 50% chance per bit, even with knowledge of the randomness-generating procedure, the implementation's internal state at the given point in time, and/or extremely many outputs of the RNG. (If the sequence was generated directly by a PRNG, ensuring future bits are unguessable this way should be done wherever the implementation finds it feasible; for example, see "Seeding and Reseeding".)

Seeding and Reseeding

If an unpredictable-random implementation uses a PRNG, the following requirements apply.

The PRNG's state length must be at least 128 bits and should be at least 256 bits.

Before an instance of the RNG generates a random number, it must have been initialized ("seeded") with an unpredictable seed, defined as follows. The seed—

The RNG should be reseeded from time to time (using a newly generated unpredictable seed) to help ensure the unguessability of the output. If the implementation reseeds, it must do so before it generates more than 267 bits without reseeding and should do so—


Examples of unpredictable-random implementations include the following:

Statistical-Random Generators

Statistical-random generators are used, for example, in simulations, numerical integration, and many games to bring an element of chance and variation to the application, with the goal that each possible outcome is equally likely. However, statistical-random generators are generally suitable only if—

If more than 20 items are being shuffled, a concerned application would be well advised to use alternatives to this kind of implementation (see "Shuffling").

A statistical-random implementation is usually implemented with a PRNG, but can also be implemented in a similar way as an unpredictable-random implementation provided it remains reasonably fast.


A statistical-random implementation generates random bits, each of which is uniformly randomly distributed independently of the other bits, at least for nearly all practical purposes. If the implementation uses a PRNG, that PRNG algorithm's expected number of state transitions before a cycle occurs and its expected number of state transitions during a cycle must each be at least 232. The RNG need not be equidistributed.

Seeding and Reseeding

If a statistical-random implementation uses a PRNG, the following requirements apply.

The PRNG's state length must be at least 64 bits, should be at least 128 bits, and is encouraged to be as high as the implementation can go to remain reasonably fast for most applications.

Before an instance of the RNG generates a random number, it must have been initialized ("seeded") with a seed described as follows. The seed—

The implementation is encouraged to reseed itself from time to time (using a newly generated seed as described earlier), especially if the PRNG has a state length less than 238 bits. If the implementation reseeds, it should do so before it generates more values than the square root of the PRNG's period without reseeding.

Examples and Non-Examples

Examples of statistical-random generators include the following:

Non-examples include the following:

Seeded Random Generators

In addition, some applications use pseudorandom number generators (PRNGs) to generate results based on apparently-random principles, starting from a known initial state, or "seed". Such applications usually care about reproducible results. (Note that in the definitions for unpredictable-random and statistical-random generators given earlier, the PRNGs involved are automatically seeded before use.)

Seeding Recommendations

An application should use a PRNG with a seed it specifies (rather than an automatically-initialized PRNG or another kind of RNG) only if—

  1. the initial state (the seed) which the "random" result will be generated from—
    • is hard-coded,
    • was based on user-entered data,
    • is known to the application and was generated using an unpredictable-random or statistical-random implementation (as defined earlier),
    • is a verifiable random number (as defined later), or
    • is based on a timestamp (but only if the reproducible result is not intended to vary during the time specified on the timestamp and within the timestamp's granularity; for example, a year/month/day timestamp for a result that varies only daily),
  2. the application might need to generate the same "random" result multiple times,
  3. the application either—
    • makes the seed (or a "code" or "password" based on the seed) accessible to the user, or
    • finds it impractical to store or distribute the "random" numbers or results (rather than the seed) for later use, such as—
      • by saving the result to a file,
      • by storing the random numbers for the feature generating the result to "replay" later, or
      • by distributing the results or the random numbers to networked users as they are generated, and
  4. any feature using that random number generation method to generate that "random" result will remain backward compatible with respect to the "random" results it generates, for as long as that feature is still in use by the application.

Meeting recommendation 4 is aided by using stable PRNGs; see "Definitions" and the following examples:

Seedable PRNG Recommendations

Which PRNG to use for generating reproducible results depends on the application. But as recommendations, any PRNG algorithm selected for producing reproducible results—


Custom seeds can come into play in the following situations, among others.


Many kinds of games generate game content using apparently-random principles, such as—

where the game might need to generate the same content of that kind multiple times.

In general, such a game should use a PRNG with a custom seed for such purposes only if—

  1. generating the random content uses relatively many random numbers (say, more than a few thousand), and the application finds it impractical to store or distribute the content or the numbers for later use (see recommendations 2 and 3), or
  2. the game makes the seed (or a "code" or "password" based on the seed, such as a barcode or a string of letters and digits) accessible to the player, to allow the player to generate the content repeatedly (see recommendations 2 and 3).

Option 1 often applies to games that generate procedural terrain for game levels, since the terrain often exhibits random variations over an extended space. Option 1 is less suitable for puzzle game boards or card shuffling, since much less data needs to be stored.

Suppose a game generates a map with random terrain and shows the player a "code" to generate that map. Under recommendation 4, the game—

Unit Testing

A custom seed is appropriate when unit testing a method that uses a seeded PRNG in place of another kind of RNG for the purpose of the test (provided the method meets recommendation 4).

Verifiable Random Numbers

Verifiable random numbers are random numbers (such as seeds for PRNGs) that are disclosed along with all the information necessary to verify their generation. Usually, of the information used to derive such numbers—

One process to generate verifiable random numbers is described in RFC 3797 (to the extent its advice is not specific to the Internet Engineering Task Force or its Nominations Committee). Although the source code given in that RFC uses the MD5 algorithm, the process does not preclude the use of hash functions stronger than MD5 (see the last paragraph of section 3.3 of that RFC).


Randomly generated numbers can serve as noise, that is, a randomized variation in images and sound. (See also Red Blob Games, "Noise Functions and Map Generation")(3). In general, the same considerations apply to any RNGs the noise implementation uses as in other cases.

However, special care should be taken if the noise implementation implements cellular noise, value noise, or gradient noise (such as Perlin noise) and uses one of the following techniques:

Wherever feasible, a cellular, value, or gradient noise implementation should use an RNG to initialize a table of gradients or hash values in advance, to be used later by the noise function (a function that outputs seemingly random numbers given an n-dimensional point).

Programming Language APIs

The following table lists application programming interfaces (APIs) implementing unpredictable-random and statistical-random RNGs for popular programming languages. Note the following:

Language Unpredictable-random Statistical-random Other
C/C++ (G) (C) xoroshiro128plus.c (128-bit nonzero seed); xorshift128plus.c (128-bit nonzero seed)
Python secrets.SystemRandom (since Python 3.6); os.urandom() ihaque/xorshift library (128-bit nonzero seed; default seed uses os.urandom()) random.getrandbits() (A); random.seed() (19,936-bit seed) (A)
Java (D) (C); (F) grunka/xorshift (XORShift1024Star or XORShift128Plus)
JavaScript crypto.randomBytes(byteCount) (node.js only) xorshift library Math.random() (floating-point) (B)
Ruby (C); SecureRandom class (require 'securerandom') Random#rand() (floating-point) (A) (E); Random#rand(N) (integer) (A) (E); (default seed uses entropy)

(A) Default general RNG implements the Mersenne Twister, which doesn't meet the statistical-random requirements, strictly speaking, but might be adequate for many applications due to its extremely long period.

(B) JavaScript's Math.random is implemented using xorshift128+ in the latest V8 engine, Firefox, and certain other modern browsers as of late 2017; the exact algorithm to be used by JavaScript's Math.random is "implementation-dependent", though, according to the ECMAScript specification.

(C) See "Advice for New Programming Language APIs" for implementation notes for unpredictable-random implementations.

(D) Java's java.util.Random class uses a 48-bit seed, so doesn't meet the statistical-random requirements. However, a subclass of java.util.Random might be implemented to meet those requirements.

(E) In my opinion, Ruby's Random#rand method presents a beautiful and simple API for random number generation.

(F) At least in Unix-based systems, calling the SecureRandom constructor that takes a byte array is recommended. The byte array should be data described in note (C).

(G) std::random_device, introduced in C++11, is not recommended because its specification leaves considerably much to be desired. For example, std::random_device can fall back to a pseudorandom number generator of unspecified quality without much warning.

Advice for New Programming Language APIs

Wherever possible, existing libraries and techniques that already meet the requirements for unpredictable-random and statistical-random RNGs should be used. For example—

If existing solutions are inadequate, a programming language API could implement unpredictable-random and statistical-random RNGs by filling an output byte buffer with random bytes, where each bit in each byte will be randomly set to 0 or 1. For instance, a C language API for unpredictable-random generators could look like the following: int random(uint8_t[] bytes, size_t size);, where "bytes" is a pointer to a byte array, and "size" is the number of random bytes to generate, and where 0 is returned if the method succeeds and nonzero otherwise. Any programming language API that implements such RNGs by filling a byte buffer ought to run in amortized linear time on the number of random bytes the API will generate.

Unpredictable-random and statistical-random implementations—

My document on random number generation methods includes details on eleven uniform random number methods; in my opinion, a new programming language's standard library ought to include those eleven methods separately for unpredictable-random and for statistical-random generators. That document also discusses how to implement other methods to generate random numbers or integers that follow a given distribution (such as a normal, geometric, binomial, or discrete weighted distribution) or fall within a given range.


There are special considerations in play when applications use RNGs to shuffle a list of items.

Shuffling Method

The first consideration touches on the shuffling method. The Fisher–Yates shuffle method does a substantially unbiased shuffle of a list, assuming the RNG it uses can choose from among all permutations of that list. However, that method is also easy to mess up (see also Jeff Atwood, "The danger of naïveté"); I give a correct implementation in another document.

Choosing from Among All Permutations

The second consideration is present if the application uses PRNGs for shuffling. If the PRNG's period is less than the number of distinct permutations (arrangements) of a list, then there are some permutations that PRNG can't choose when it shuffles that list. (This is not the same as generating all permutations of a list, which, for a sufficiently large list size, can't be done by any computer in a reasonable time.)

The number of distinct permutations is the multinomial coefficient m! / (w1! × w2! × ... × wn!), where m is the list's size, n is the number of different items in the list, x! means "x factorial", and wi is the number of times the item identified by i appears in the list. Special cases of this are—

In general, a PRNG with state length k bits, as shown in the table below, can't choose from among all the distinct permutations of a list with more items than the given maximum list size n (k is the base-2 logarithm of n!, rounded up to an integer). (Note that a PRNG with state length k bits can't have a period greater than 2k, so can't choose from among more than 2k permutations.)

State length (k) Maximum list size (n)
64 20
128 34
226 52
256 57
512 98
525 100

A PRNG with state length less than the number of bits given below (k) can't choose from among all the distinct permutations of a list formed from p identical lists each with n different items, as shown in this table (k is the base-2 logarithm of ((np)! / p!n), rounded up to an integer).

Number of lists (p) Items per list (n) Minimum state length (k)
1 20 62
2 20 140
4 20 304
1 52 226
2 52 500
1 60 273

Whenever a statistical-random implementation or seeded RNG is otherwise called for, if an application is expected—

The PRNG in question should—

Hash Functions

A seemingly random number can be generated from arbitrary data using a hash function.

A hash function is a function that takes an arbitrary input of any size (such as a sequence of bytes or a sequence of characters) and returns an output with a fixed size. That output is also known as a hash code. (By definition, hash functions are deterministic. The definition includes a PRNG that takes the input as a seed and outputs a random number of fixed size(4).)

A hash code can be used as follows:

For such purposes, applications should choose hash functions designed such that—

GPU Programming Environments

Because, in general, GL Shading Language (GLSL) and other programming environments designed for execution on a graphics processing unit (GPU)—

random number generators for such environments are often designed as hash functions, because their output is determined solely by the input rather than both the input and state (as with PRNGs). Moreover, some of the hash functions which have been written in GLSL give undesirable results in computers whose GPUs support only 16-bit binary floating point numbers and no other kinds of numbers, which makes such GPUs an important consideration when choosing a hash function.


In this document, I made the distinction between statistical-random and unpredictable-random generators because that is how programming languages often present random number generators — they usually offer a general-purpose RNG (such as C's rand or Java's java.util.Random) and sometimes an RNG intended for information security purposes (such as

What has motivated me to write a more rigorous definition of random number generators is the fact that many applications still use weak RNGs. In my opinion, this is largely because most popular programming languages today—


In conclusion, most applications that require random numbers usually want either unpredictability ("cryptographic security"), or speed and high quality. I believe that RNGs that meet the descriptions specified in the Unpredictable-Random Generators and Statistical-Random Generators sections will meet the needs of those applications.

In addition, this document recommends using unpredictable-random implementations in many cases, especially in information security contexts, and recommends easier programming interfaces for both unpredictable-random and statistical-random implementations in new programming languages.

I acknowledge—

Request for Comments

Feel free to send comments. They could help improve this page.

Comments on any aspect of the document are welcome, but answers to the following would be particularly appreciated.


(1) If a number generator uses a nonuniform distribution, but otherwise meets this definition, then it can be converted to one with a uniform distribution, at least in theory, by applying the nonuniform distribution's cumulative distribution function (CDF) to each generated number. A CDF returns, for each number, the probability for a randomly generated variable to be equal to or less than that number; the probability is 0 or greater and 1 or less. Further details on CDFs or this kind of conversion are outside the scope of this document.

(2) This statement appears because multiple instances of a PRNG automatically seeded with a timestamp, when they are created at about the same time, run the risk of starting with the same seed and therefore generating the same sequence of random numbers.

(3) Noise implementations include cellular noise, value noise, gradient noise, colored noise (including white noise and pink noise), and noise following a Gaussian or other probability distribution. A noise implementation can use fractional Brownian motion to combine several layers of cellular, value, or gradient noise by calling the underlying noise function several times.

Note that usual implementations of noise (other than cellular, value, or gradient noise) don't sample each point of the sample space more than once; rather, all the samples are generated (e.g., with an RNG), then, for colored noise, a filter is applied to the samples.

(4) Note that some PRNGs (such as xorshift128+) are not well suited to serve as hash functions, because they don't mix their state before generating a random number from that state.


This page is licensed under Creative Commons Zero.