How random is a random number generator?

Updated 2026-08-27 ยท about 8 minute read

Ask a computer for a random number and you will get one. Whether it is random depends on which generator answered, and the difference is invisible until it matters โ€” at which point it can matter enormously.

Most random numbers are not random

A computer is a deterministic machine. Given the same input it produces the same output, every time, which is precisely the property that makes it useful and precisely the property that makes randomness hard.

So most "random" numbers are the output of an algorithm that produces a sequence statistically resembling randomness while being entirely predictable if you know where it started. These are pseudorandom number generators, and JavaScript's Math.random() is one.

True randomness has to come from outside the algorithm โ€” physical processes like thermal noise, radioactive decay, or the timing jitter of interrupts. Modern processors have hardware instructions that sample such noise, and operating systems mix these sources into an entropy pool.

Pseudorandom generators and seeds

A PRNG starts from a seed and applies a formula repeatedly. Same seed, same sequence โ€” always.

This determinism is often a feature. Games use seeded generators so a world can be regenerated from a short code. Simulations use them so results are reproducible. Tests use them so a failure can be replayed.

The problem is that PRNGs are predictable by design. Observe enough output from a simple generator and you can determine its internal state, and from there predict every number it will ever produce. This has cost real money: online poker sites have been broken this way, with attackers reconstructing the shuffle from a handful of visible cards and then knowing every player's hand.

Math.random() makes no security promises whatsoever. The specification explicitly declines to require any. It is fine for a visual effect, a random tip, a demonstration โ€” and unfit for anything an adversary would benefit from predicting.

Cryptographic randomness

A cryptographically secure generator adds one guarantee: even given every previous output, an attacker cannot predict the next one better than by chance, and cannot work backwards to earlier outputs.

In the browser this is crypto.getRandomValues(), which draws from the operating system's entropy pool. Every tool on this site that needs randomness uses it โ€” the random number generator, the password generator, the dice roller, the coin flip, the random picker and the UUID generator.

Using the cryptographic generator even for a dice roll is not overkill; it costs nothing and removes an entire class of question about whether the result is fair.

Modulo bias: the invisible skew

Here is the subtle bug that appears in an enormous amount of production code, and it survives because the output still looks random.

Suppose you want a number from 1 to 6 and your generator gives you a byte, 0 to 255. The obvious approach is (byte % 6) + 1.

But 256 does not divide by 6. It gives 42 complete cycles of six, using values 0 to 251, and then four left over: 252, 253, 254, 255 โ€” which map to 1, 2, 3, 4. So those four faces come up 43 times per 256 rolls while 5 and 6 come up 42 times. The die is loaded by about 2% in favour of the low numbers.

With a die that is a curiosity. Applied to password generation across a large character set, it systematically reduces entropy and skews which characters appear. Applied to a shuffle, it biases the deck.

The fix is rejection sampling: discard values that fall in the incomplete final cycle and draw again. In the example, throw away 252 to 255 and re-roll. It wastes a tiny fraction of draws and produces a genuinely uniform result. Every random tool on this site does this, which is why a run of twenty words from the random word generator is drawn uniformly rather than skewed toward the start of the list.

Shuffling is harder than it looks

The intuitive shuffle โ€” walk the list and swap each item with a random other item โ€” is subtly wrong. It produces nn equally likely outcomes, which does not divide evenly into the n! possible orderings, so some arrangements are more likely than others.

The correct algorithm is the Fisherโ€“Yates shuffle: walk from the end, swapping each item with a random item at or before its position. That single constraint makes every permutation equally likely.

A famous case: in 2004 an online casino's shuffle used a 32-bit seed, giving about four billion possible shuffles against the 52! โ€” roughly 8 ร— 1067 โ€” orderings of a real deck. The overwhelming majority of possible shuffles could never occur, and the ones that could were enumerable.

The random picker and team generator use Fisherโ€“Yates with cryptographic randomness, which between them removes both failure modes.

When the difference actually matters

Being honest about this: for most everyday uses it does not.

It does not matter for picking a restaurant, choosing who goes first, splitting a class into teams, or rolling dice for a board game. Nobody is mounting a cryptographic attack on your family quiz, and a 2% bias in a coin flip will never be noticed.

It matters a great deal for anything security-related โ€” passwords, keys, tokens, session identifiers, password reset links โ€” and for anything with money or fairness at stake, such as prize draws, lotteries and gambling. It also matters for scientific simulation, where a poor generator can produce correlations that quietly invalidate results.

The practical rule: use a cryptographic generator by default. It is not slower in any way you would notice, and it means you never have to work out which category you are in. If a random value protects something, check the result with the password strength checker, and see how long a password should be for what that number means.

Pikkit has the full set of random tools, and Random & Fun collects them together.

Try the tool

Frequently asked questions

Is Math.random() secure?

No. The JavaScript specification makes no security guarantees about it, and its output can be predictable. Use crypto.getRandomValues() for anything involving passwords, keys or tokens.

What is the difference between pseudorandom and truly random?

A pseudorandom generator produces a deterministic sequence from a seed, so the same seed always gives the same numbers. True randomness comes from a physical process such as thermal noise.

What is modulo bias?

When you fold a large random range into a smaller one with a remainder, the leftover values make some outcomes slightly more likely. Rejection sampling โ€” discarding and redrawing โ€” fixes it.

Are online dice rollers fair?

They can be, if they use a cryptographic generator and avoid modulo bias. The tools here do both, so every face is exactly equally likely.

Does randomness quality matter for picking a name from a list?

Practically, no โ€” a small bias is unnoticeable in a raffle among friends. It matters for passwords, keys, prize draws with real value, and scientific simulation.