How random number generators work
How computers produce randomness, why crypto.getRandomValues beats Math.random, and how rejection sampling removes bias from a range.
Pseudo-random versus cryptographic randomness
Most everyday randomness comes from a pseudo-random number generator, a formula that starts from a seed and produces a stream of values that only look random. JavaScript's Math.random is one of these, and while it is fine for shuffling a slideshow, its output can be predicted if you learn the internal state. Cryptographically secure generators instead gather entropy from the operating system, seeded by hardware noise and other unpredictable events. This tool uses crypto.getRandomValues, the secure source built into every modern browser, so results are suitable for draws where fairness matters.
Why a naive range can be biased
A common shortcut for fitting a raw random integer into a range is the remainder operator, value modulo range. The problem is that a 32-bit random number holds just over four billion possibilities, and unless your range divides that total evenly, some remainders occur slightly more often than others. Over many draws this quietly favors the lower numbers in your range. For a coin flip the skew is invisible, but for anything audited or repeated it is a real flaw worth avoiding.
How rejection sampling fixes it
To keep every value equally likely, the generator finds the largest whole multiple of your range that fits inside the 32-bit space and discards any raw number above it before taking the remainder. Throwing away that thin sliver of high values means the numbers that remain map onto your range perfectly evenly. The cost is that a draw occasionally repeats, but the rejection rate is tiny, so the tool still returns results instantly. This is the same technique cryptographic libraries use for unbiased range reduction.
Drawing unique numbers without repeats
When you ask for distinct values, sorting or reshuffling the entire range would be wasteful for a wide span like 1 to a million. Instead the tool runs a partial Fisher-Yates shuffle: it swaps only as many positions as you requested, pulling each pick from a pool that shrinks by one after every draw. That keeps memory and time proportional to the count you asked for, not the size of the range, while every ordering of the winners stays equally likely.