Is a spin wheel really random?
A well-built online wheel is as random as your device can make it. SpinDecide draws the winner from the browser's cryptographic random generator, removes a subtle bias called modulo bias, and only then animates the wheel to that slice. Here is how it works, and how you can check it yourself.
How does a computer make a random number?
A computer follows instructions exactly, so software needs a trick to produce chance. A pseudo-random number generator (PRNG) starts from a number called a seed and runs it through a formula that produces a long stream of values which look random and pass statistical tests. Anyone who knows the formula and the internal state can predict every value that follows.
A cryptographically secure generator (CSPRNG) is built so that prediction is not practical, even for someone who has seen many earlier outputs. Operating systems feed it with hard-to-guess entropy, such as timing noise from hardware, and the standards for these generators are published by bodies like the US National Institute of Standards and Technology (NIST SP 800-90A).
| Ordinary PRNG | Cryptographic generator | |
|---|---|---|
| In the browser | Math.random() | crypto.getRandomValues() |
| Looks random in tests | Yes | Yes |
| Hard to predict from past outputs | No, not by design | Yes, that is its purpose |
| Typical use | Games, animation, simulations | Passwords, keys, draws people must trust |
Why not just use Math.random()?
Math.random() is the quick random function built into JavaScript. For shuffling a playlist or scattering confetti it is fine. But the language specification leaves the algorithm up to the browser, and MDN's documentation states plainly that it does not provide cryptographically secure numbers. Chrome's V8 engine, for instance, uses a fast generator called xorshift128+, whose internal state can in principle be worked out from a handful of outputs.
For choosing a pizza, none of that matters. For a giveaway with a real prize or a stream where viewers suspect a fix, the stronger source is worth it, and crypto.getRandomValues(), part of the Web Crypto API in every modern browser, costs nothing extra. SpinDecide uses it for every spin, shuffle and team split. Only if a browser lacked the Web Crypto API entirely would the code fall back to Math.random().
What is modulo bias, and how is it avoided?
A random generator hands out raw numbers in a fixed range, and the wheel has to turn one into a slice number. The obvious trick is the remainder after division (the "modulo"): divide by the number of slices and keep what is left over. That quietly favours some slices.
Here is a small example. Suppose the generator gives a number from 0 to 9 and the wheel has 3 slices. Taking the remainder after dividing by 3 gives:
- Slice 0 from 0, 3, 6 and 9 (four ways)
- Slice 1 from 1, 4 and 7 (three ways)
- Slice 2 from 2, 5 and 8 (three ways)
Slice 0 wins 40% of the time instead of 33%. The fix is rejection sampling: if the raw number is 9, throw it away and draw again. Now each slice has exactly three ways to win.
SpinDecide works with 32-bit numbers, from 0 to 4,294,967,295, so the imbalance would be tiny, roughly one part in a billion. The code removes it anyway: it calculates the largest multiple of the slice count that fits, rejects anything above it and redraws. With 7 slices, only 4 of the 4.29 billion possible values are ever rejected, so the redraw almost never happens, but when it does, fairness is exact.
Why does SpinDecide pick the winner before the wheel moves?
A physical wheel's result depends on how hard it is pushed and on friction. A digital wheel could imitate that with a physics simulation, but then the outcome would depend on animation timing, screen refresh rate and rounding, which are hard to reason about and impossible to audit.
So the order is reversed. The moment you press Spin, the app chooses the winning slice with the cryptographic generator. It then picks a second random number to decide where inside that slice the pointer will stop, keeping a safety margin from both edges (12% of the slice's width, or 4 degrees on wide slices, whichever is smaller). Finally it plans a rotation of several full turns, seven or more on the normal five-second setting, and slows the wheel with a smooth ease-out curve so that it settles on that exact point.
The spin looks natural and rarely stops in the same spot twice, yet the odds are fixed before the first frame is drawn.
Can the pointer ever disagree with the result?
No. Because the stopping point is chosen inside the winning slice and away from its borders, the pointer cannot end up on a line or in a neighbouring slice. As a final safeguard, when the animation finishes the app reads which slice is actually under the pointer and reports that one, so the pop-up, the results history and what you see on screen always match.
If you have your device set to reduce motion, the spin is shortened to about a second with a single turn. The winner is chosen in exactly the same way.
How do weights change the odds?
With weights switched off, every slice is the same size and the winner is a uniform draw: with 8 options, each has a 1 in 8 chance. With weights on, each option's chance is its weight divided by the total of all weights, and its slice is drawn at exactly that share of the circle. Weights of 3, 2 and 1 give chances of 50%, 33% and 17%, and the slices are half, a third and a sixth of the wheel.
So a weighted wheel is still honest, because what you see is what you get, but it is no longer equal. If other people rely on the result, tell them before you spin. The coin flip vs wheel probability guide has worked examples of weighted odds.
Why do streaks happen on a fair wheel?
Fair does not mean evenly spread. Each spin is independent, so a slice that has just won is exactly as likely to win again. Expecting a "due" result after a run of the other one is known as the gambler's fallacy.
Streaks are much more common than intuition suggests. In 100 flips of a fair coin, which is the same as 100 spins of a two-slice wheel, there is roughly an 80% chance of at least one run of six identical results in a row, and about a 54% chance of a run of seven or more. On a ten-slice wheel, the same slice comes up twice in a row one time in ten. A streak on its own is not evidence that a wheel is rigged.
How can you test a wheel yourself?
You do not need to trust anyone's word, including ours. The test is simple: spin many times, count how often each slice wins, and compare the counts with what fair odds predict.
- Make a wheel with a few equal options, say six numbers on the random number wheel, and choose the short spin length.
- Spin a few hundred times. Open Results, press Copy, and paste the list into a spreadsheet.
- Count each option. With 600 spins and 6 options, each should land near 100, but not exactly.
To judge whether the spread is normal, statisticians use a chi-square goodness-of-fit test. For each option, take the difference between the observed and expected count, square it, divide by the expected count, then add the results up. Suppose you got 94, 108, 101, 97, 112 and 88. The total is (36 + 64 + 1 + 9 + 144 + 144) ÷ 100 = 3.98. For six options, a fair wheel stays below about 11.07 in 95 out of 100 such tests, so 3.98 is entirely ordinary. Expect a fair wheel to fail roughly one test in twenty by chance; that is what the 5% threshold means. A wheel that fails again and again with a big sample is the one to worry about.
Comfortable with the browser console? A short loop that calls SDWheel.pickIndex(SDWheelApp.state.items) tens of thousands of times and tallies the results runs the same selection code as a real spin, without the animation. The coin flip tool also keeps running heads and tails counts if you want a quick two-option check.
What randomness cannot promise
A fair draw guarantees equal chances, not equal outcomes. If you spin a class list twenty times, some students will be picked twice and others not at all. When everyone should get a turn, switch on Remove the winner after each spin, as the name picker for teachers does, so each name can only come up once.
Randomness also cannot prove itself to an audience. If a prize is at stake, show the entries, record the spin and agree that the first spin counts, as described in the fair giveaway guide.
Frequently asked questions
Can someone rig an online spinner wheel?
A site can be built to cheat, which is why SpinDecide's code runs openly in your browser and picks the winner with the Web Crypto API before the animation starts. For public draws, show the entry list and record the spin so viewers can see nothing changed.
Does clicking harder or at a certain moment change the result?
No. The winner is chosen the instant you press Spin, from a cryptographic random number. Timing, click speed, the number of previous spins and your device's speed have no effect on which slice wins.
Why did the same name come up twice in a row?
Every spin is independent, so a name that just won has the same chance as any other on the next spin. On a ten-slice wheel a repeat happens about one spin in ten. Turn on Remove the winner if repeats are not wanted.
Is crypto.getRandomValues truly random?
It is a cryptographically secure pseudo-random generator seeded by your operating system with unpredictable entropy. It is not a physical process like radioactive decay, but its output cannot practically be predicted, which is the property a fair draw needs.
How many spins do I need to test a wheel?
A few hundred spins on a wheel with a handful of options is enough to spot a large bias. To detect small differences you need thousands, which is easier with the browser console method described above than by pressing Spin by hand.
Sources
- MDN Web Docs: Math.random()
- MDN Web Docs: Crypto.getRandomValues()
- W3C: Web Cryptography API
- V8 blog: There’s Math.random(), and then there’s Math.random()
- NIST SP 800-90A Rev. 1: Recommendation for Random Number Generation Using Deterministic Random Bit Generators
- NIST/SEMATECH e-Handbook of Statistical Methods: Chi-square goodness-of-fit test
- Wikipedia: Gambler’s fallacy