Ad Space
Random Number(s)
Ad Space

Why This Generator Uses a Cryptographically Secure Random Source

Most random numbers you'll ever encounter in JavaScript come from Math.random(), a fast pseudorandom generator that is deterministic under the hood and never intended to resist prediction. This calculator instead uses the Web Crypto API's crypto.getRandomValues(), which draws from the operating system's cryptographically secure random source — the same category of randomness used to generate encryption keys — so its output is suitable for any purpose where the numbers genuinely need to be unpredictable, not just look random.

Avoiding Modulo Bias

Mapping a random byte into a smaller range with the modulo (remainder) operator seems like an obvious approach, but it introduces a subtle unfairness whenever the range doesn't evenly divide the number of possible byte values. A byte has 256 possible values (0 through 255); if the requested range has, say, 100 possible outcomes, 256 divided by 100 doesn't come out even, so the outcomes near the bottom of the range end up very slightly more likely than the ones near the top, purely because of how the leftover bytes distribute across the modulo.

This calculator avoids that with rejection sampling. Given a 32-bit random draw and a requested range, any value above a computed cutoff is discarded and redrawn rather than folded back into the range unevenly:

cutoff=2321((2321)modrange)\text{cutoff} = 2^{32} - 1 - \left((2^{32} - 1) \bmod \text{range}\right)

range: the count of possible outcomes, maximum minus minimum plus one.

cutoff: the largest multiple of the range that still fits within the sampled 32-bit space, above which a drawn value is rejected and redrawn.

Every draw at or below the cutoff maps onto the requested range with the remainder operator, and because the space below the cutoff is an exact multiple of the range, every outcome gets exactly the same number of raw values mapping to it:

result=min+(rawmodrange)\text{result} = \text{min} + (\text{raw} \bmod \text{range})

Worked Example: Rolling a Fair 3-Sided Outcome from a Byte

Suppose a range of exactly 3 possible outcomes needs to be drawn from a single random byte (256 possible values, 0 through 255). 256 divided by 3 is 85 remainder 1 — so values 0 through 254 (255 values, a clean multiple of 3) map fairly evenly across the 3 outcomes, but byte value 255 is the one leftover value with no fair partner. Discarding 255 and drawing again whenever it comes up keeps all 3 outcomes exactly equally likely; folding it in anyway (255 mod 3 equals 0) would make the first outcome very slightly more common than the other two.

Unique vs. Repeating Numbers

When repeats are not allowed, the count of numbers you can generate is capped by how many distinct integers exist in the chosen range — asking for more unique numbers than the range actually contains is mathematically impossible, and this calculator checks for that case explicitly before generating anything.

Where True Randomness Matters

Drawing raffle winners, shuffling a deck for a real-money game, generating one-time passwords or session tokens, and any statistical sampling that needs to be defensible against a biased or predictable process are all situations where pseudorandom output (or biased mapping) can be a real problem, not just an academic one. A cryptographically secure, unbiased generator like the one used here is the appropriate tool whenever the numbers need to hold up under scrutiny.

Common Random Number Mistakes

Using Math.random() for anything security-sensitive is the most consequential mistake, since its output can potentially be predicted by an attacker who studies enough samples. Applying the modulo operator directly to a random value without correcting for bias is a subtler, easy-to-miss error that silently skews results toward the low end of a range. Assuming "random" and "well-distributed over a small sample" are the same thing is another common misconception — even a perfectly fair generator will occasionally produce short runs of similar-looking numbers by chance.

Random Number Terms You Should Know

Pseudorandom — generated by a deterministic algorithm that appears random but can, in principle, be predicted or reproduced.

Cryptographically Secure Random Number Generator (CSRNG) — a random source designed so its output cannot be feasibly predicted, suitable for security-sensitive use.

Modulo Bias — the slight unfairness introduced when a random value is mapped into a smaller range using the remainder operator without correcting for an uneven fit.

Rejection Sampling — discarding and redrawing any random value that falls outside a fair, evenly-divisible portion of the sampled space.

Frequently Asked Questions

Why use crypto.getRandomValues() instead of Math.random()?

Math.random() uses a fast, deterministic pseudorandom algorithm that is not designed to resist prediction and is unsuitable for anything security-sensitive. crypto.getRandomValues(), part of the Web Crypto API, draws from the operating system's cryptographically secure random source, the same category of randomness used to generate encryption keys.

What is modulo bias and how does this calculator avoid it?

Modulo bias happens when you map a random byte to a smaller range using the remainder operator, and the range does not evenly divide the number of possible byte values, so some outcomes become slightly more likely than others. This calculator avoids it with rejection sampling: it discards any random value that falls in the leftover, unevenly-distributed portion of the range and draws again, so every outcome in the requested range stays equally likely.

What happens if I ask for more unique numbers than fit in the range?

If unique numbers are required, the count of numbers you can generate is limited by how many distinct values exist between the minimum and maximum. Asking for more unique numbers than that range contains is impossible, and this calculator shows a clear message instead of an incomplete or incorrect list.

Ad Space