Random Number Picker — Unbiased Draws, Name Lotteries, and a Seed You Can Re-run
Whole numbers, decimals, or names you paste in — drawn from the browser's cryptographic generator using a mask-and-reject step instead of a modulo, so every outcome really has the same chance. Draws can be without repetition, a list can be split into even groups, and a seed mode makes the whole draw reproducible so you can show somebody the result was picked once, not re-rolled until it looked good. There is a measured side-by-side of the modulo bias. Nothing you type leaves this device.
| # | Result | From line | Words spent |
|---|
Groups
| Group | Size | Members |
|---|
Record of this draw
Why a modulo is not the same as a fair draw
Taking one random byte and computing byte % 6 is the usual shortcut, and 256 is not a multiple of 6: four of the six outcomes get one extra winning byte out of 256. The table below runs both methods on the same source, so the gap is something you can read rather than take on trust.
| Outcome | byte % 6 | Expected | mask + reject |
|---|
The generator, and seed mode
Three small jobs that go wrong easily
Three jobs that look trivial and go wrong in practice: pick a number in a range, pick several without repetition, and pick names out of a list you pasted in. The range picker takes whole numbers or decimals, the list picker draws without putting anyone back, and either can be split into even groups instead. Every draw comes off the browser’s cryptographic generator, and the count of 32-bit words spent to get the result is printed next to it - the honest measure of how much randomness a draw really needed.
The record under the table exists for a specific reason. A draw is only worth something if it can be shown afterwards: the source, the pool, each result with its index, and the moment it was taken. Copy that into the thread where the dispute started instead of saying “I swear it was random”.
Why the generator matters more than the range
Math.random() is fine for a shuffle in a game and wrong for anything anybody might contest, because it is a pseudo-generator whose state lives inside the JavaScript engine: it can be predicted, and depending on the engine it only carries 32 bits of seed. The draws here take their words from crypto.getRandomValues, which the browser refills from the operating system’s entropy pool.
The second place things go wrong is the mapping from a word to a range, and that is what the modulo-bias comparison demonstrates. A word gives you 4,294,967,296 values; if you want six outcomes and use the remainder of a byte, you are folding 256 values onto six buckets. 256 is not a multiple of 6, so four buckets end up holding 43 bytes and two hold 42. The favoured outcomes come up 16.796875% of the time where a fair draw would be 16.666667% - about one thirteenth of a percentage point, which is nothing in a raffle and decisive in anything with a threshold. The sampler masks the word down to the bits the pool actually needs and redraws when the masked value lands past the end, so the discarded draws are the cost of equal odds. The two columns use the same source, so you can watch the gap rather than take it on trust, and the word counts show what the redraws cost.
For draws without repetition there are two routes and one is picked by size. A small pool is laid out in memory and shuffled partially (a Fisher-Yates cut short), so no outcome can repeat by construction. A large pool is sampled with a set of “already taken” values, and a repeat is thrown away rather than counted. Both keep every combination equally likely; the note under the table says which one ran.
Re-runnable seed mode, and what it is not for
Tick seed mode and type a seed, and the same seed with the same inputs returns the same draw. That is for checking a result, arguing about it later, or reproducing a bug report - a deterministic stream derived from the text you typed, warmed up before use.
It is explicitly not a way to get a fair pick between contestants, because the seed is public, and a public seed is something a determined participant can search: a few thousand tries finds a seed that makes their name come first. If anyone could gain from choosing the outcome, use the crypto source and record it.
The limits, stated
Five hundred draws at a time, two thousand list entries, decimal places up to nine, and pools up to 2^53 outcomes - past that, integers stop being exact and the sampler refuses instead of quietly sampling a smaller pool than it claims. Blank lines in a list are dropped and counted, repeated names are kept as separate entries because spelling is the only identity a list has, and if the groups do not divide evenly the note under the table says how many are one bigger and that the shuffle, not the names, decided which.
Nothing is uploaded: the list, the seed and the results are handled by the script in your own browser, never sent off somewhere to be drawn, and gone when you close the tab.