Random number generator: definition and how it works

Vibrant green numbers on a computer screen, showcasing binary code and data streams.

Photo by Tibe De Kort on Pexels

A random number generator (RNG) is any system, algorithm, or physical process that produces a sequence of numbers in a way that cannot be predicted in advance. The term covers two distinct families: pseudo-random number generators (PRNGs), which use mathematical formulas, and true random number generators (TRNGs), which draw on physical events like electronic noise or radioactive decay. Both types are used in software development, cryptography, statistics, and gambling, but they aren't interchangeable.

Pseudo-random vs true random

A pseudo-random number generator starts with a value called a seed and runs it through a deterministic algorithm to produce a long stream of numbers that look random. Given the same seed, the algorithm always produces the same sequence. That's not a flaw for most uses: statistical simulations, video game level generation, and software testing all work fine with PRNGs because the outputs are statistically random enough for those purposes.

True random number generators work differently. They measure an unpredictable physical event, such as atmospheric noise, thermal noise in a resistor, or the timing between keystrokes, and convert it into a number. There's no algorithm to reverse-engineer and no seed to replay. Services like RANDOM.ORG use atmospheric radio noise to produce true random numbers available via an API. Hardware security modules inside servers do the same thing at a chip level for cryptographic keys.

The practical difference: for a lottery draw or a cryptographic key, you want true randomness. For a Monte Carlo simulation running 10 million iterations, a high-quality PRNG is fast and sufficient.

How a PRNG algorithm works

The most widely used PRNG design is the Mersenne Twister, published by Makoto Matsumoto and Takuji Nishimura in 1998. It produces a period of 2^19937 − 1 numbers before repeating, a number so large it's effectively infinite for any practical use. Modern programming languages ship with it by default: Python's random module, PHP's mt_rand(), and Ruby's rand() all run on Mersenne Twister.

For security-sensitive work, Mersenne Twister isn't appropriate. Its internal state can be reconstructed after observing 624 consecutive outputs. Cryptographically secure PRNGs (CSPRNGs) like ChaCha20 or the Fortuna algorithm are designed specifically to prevent that kind of state recovery. Operating systems expose CSPRNGs through interfaces like /dev/urandom on Linux and BCryptGenRandom on Windows.

Random number generators in gambling

Online casinos rely on certified RNGs to determine every outcome in digital games. A slot spin, a card deal in online blackjack, or a roulette ball landing position is all decided by an RNG before any animation plays. Regulators in most licensed jurisdictions require the RNG to be tested by an independent laboratory, such as eCOGRA or BMM Testlabs, before a game goes live. The testing confirms that the output distribution matches what the RTP (return to player) percentage promises over millions of simulated rounds.

This is why online slots can guarantee a stated RTP: the RNG produces statistically uniform outputs, so over a large enough sample the payback converges toward the published figure. Individual sessions can deviate sharply, but the long-run math holds.

In live casino games, the RNG is replaced by genuine physical randomness: a real dealer shuffles real cards in front of a camera. The two systems are kept strictly separate in regulated markets, which is why live casino products require a different certification pathway than their digital counterparts.

RNG testing and certification

Independent testing labs put RNGs through a battery of statistical tests to check for bias. The most common test suite is the NIST Statistical Test Suite, which runs 15 different tests on a bitstream looking for patterns, clustering, or periodicities that shouldn't appear in truly random data. An RNG that passes all 15 at the required significance level earns a clean certification.

Casinos must recertify their RNG whenever the underlying software changes. A failed test doesn't always mean fraud: it can indicate a subtle implementation bug in how the seed is refreshed or how the output is mapped to game outcomes. Either way, the game gets pulled until the issue is fixed and the lab signs off again.

Everyday uses outside gambling

RNGs appear in contexts most people don't think about. Every TLS connection your browser opens to an HTTPS site uses an RNG to generate session keys. Password managers use CSPRNGs to create credentials you couldn't guess in a thousand years. Drug trials use RNGs to assign patients to treatment or control groups, removing experimenter bias. Weather forecasting models use them to initialize ensemble runs that quantify forecast uncertainty.

Video games use PRNGs to generate terrain, loot drops, and enemy behaviour. Some games expose the seed deliberately, letting speedrunners pick seeds that produce favourable level layouts. Minecraft world generation works this way: share a seed and two players get identical worlds.

When randomness fails

Poor RNG implementations have caused real-world damage. In 1999, a flaw in Netscape's SSL implementation meant the browser seeded its PRNG using the process ID and the current time, both of which an attacker could guess. In 2008, the Debian OpenSSL package accidentally removed two lines of code that added entropy to the key generation process, producing only 32,768 distinct keys instead of billions. Every SSH key generated on a Debian or Ubuntu system between 2006 and 2008 was potentially compromised.

The lesson from both cases: an RNG is only as good as its entropy source and its implementation. Algorithmic correctness matters, but so does seeding. A perfect algorithm seeded with a predictable value produces predictable output.

Generating random numbers in code

Most languages make basic random number generation trivial. In Python, import random; random.randint(1, 100) returns a pseudo-random integer between 1 and 100. For security work, use import secrets; secrets.randbelow(100) instead, which draws from the operating system's CSPRNG. The secrets module was added to Python in version 3.6 specifically because developers were reaching for random in contexts where it wasn't safe.

JavaScript in a browser environment exposes Math.random() for general use and crypto.getRandomValues() for cryptographic work. The distinction maps neatly onto the PRNG versus CSPRNG split.

Choosing the right tool is straightforward: if the output affects security, use a CSPRNG; for everything else, a well-implemented PRNG is fast, convenient, and statistically adequate.