Toolphy

How Random Number Generators Work (and Stay Fair)

Last updated:

Every "random" button hides a choice: where does the unpredictability come from? Some systems measure real-world noise, others run a formula that only looks random. Knowing the difference explains why a lottery can be provably fair while a programmer's quick % 10 trick quietly favours some numbers.

True randomness vs pseudo-randomness

A PRNG is not a flaw. For simulations, games and most UI work it is fine, and it is fast. It becomes a problem only when unpredictability must be unguessable, such as in cryptography or a high-stakes draw.

Uniformity: what "fair" means here

A fair generator produces a uniform distribution: over the range 1–100, every value should have the same probability, 1 in 100. Fairness is not "looks varied" — a sequence like 3, 3, 7, 3 can be perfectly random, and a sequence that never repeats is often less random. People mistake clustering for bias because true randomness clusters more than intuition expects.

The modulo bias trap

A common shortcut maps a random integer onto a smaller range with the remainder operator. Suppose a generator returns a byte, 0–255, and you want 0–9 via value % 10. There are 256 possible inputs; dividing by 10 leaves 6 as a remainder. So the digits 0 through 5 each appear 26 times and 6 through 9 appear 25 times. Six values are slightly more likely — a hidden bias most people never notice.

Target valueTimes it occurs (of 256)Probability
0–52610.156%
6–9259.766%

The fix is rejection sampling: discard inputs in the uneven tail and redraw, or scale the range so the total is evenly divisible. Good libraries do this automatically; writing it by hand is where the bias creeps in.

Seeds and reproducibility

Because a PRNG is deterministic, its seed controls everything. Math.random() in JavaScript seeds itself once and is not suitable for security. A reproducible seed is a feature in testing — the same seed yields the same sequence, so a failing case can be replayed — but a liability if an attacker can guess the seed and predict "random" values.

Cryptographic random numbers

When unpredictability matters, use a cryptographically secure generator, such as crypto.getRandomValues() in the browser or the operating system's entropy pool. These are designed so that past outputs reveal nothing about future ones. For a public prize draw this is the honest choice, because no one — not even the organiser — can bias the result after the fact.

Common mistakes

What makes a draw believable

Fairness is two things: an unbiased source and a process anyone can inspect. Freeze the pool, publish the count, use a uniform generator, and record the result. A well-implemented random number generator removes the temptation to fudge — and the suspicion of it.

Generate integers or decimals in any range with our random number generator. For the surrounding process, see how to randomly pick a winner fairly, and for precision in your results see the percent error formula.

Try the Random Number Generator →