Number Wheel
A random number you can defend: 1–10 by default (36° per segment), stretchable to 1–100 (3.6° slivers), every value exactly equally likely. Those angles are computed at build time by the same engine that runs the wheel.
Spin: 1 to 10
Set a different maximum below the wheel, or edit the list directly for a custom set.
Where a fair number draw matters
Turn order in board games. Which kid picks the movie this week. Which team presents first. Countdown-style challenges ("do that many push-ups"). Picking a winner from numbered raffle stubs. In every one of those, the person who "thinks of a number" holds invisible power — the wheel takes it away from everyone equally. For classroom use, pair a number with each student and the wheel becomes a cold-call picker nobody can accuse of bias.
Everything below is a walk through what the engine actually does with this preset. Every
angle, percentage and count on this page is computed at build time by the same code that runs
the wheel, and the worked draws use scripted bytes so they can be replayed — a live spin draws
its bytes from crypto.getRandomValues instead. How segments are sized and coloured
at every wheel size has its own guide,
Segment geometry and colours; the full
mechanism is on the methodology page, and the rest of the guides
are collected at /guides/.
What the preset is, and how to change it
The number wheel is a plain list: the labels "1" through "10", generated in order, loaded into the same editable entry list every other wheel uses. The Numbers on the wheel box regenerates that list as 1 through whatever maximum you type, up to the 100-entry cap; anything else — a letter, a decimal, a number outside that span — produces an error under the box and leaves the current list untouched. Because the entries are ordinary text, the list itself remains yours to edit: delete the numbers you do not want, paste a set of your own, or type labels that are not numbers at all. Edited lists are saved in your browser's local storage so they survive a reload, and Reset list puts the default 10 numbers back.
From 10 segments to 100
A wheel of N entries is divided into N equal segments of 360/N degrees, in list order, with every boundary computed as an exact multiple. At 1–10 each segment spans 36° and wins 10% of the time; at 1–100 each is a 3.6° sliver at 1%, and the labels get tiny — that is the honest geometry of cramming a hundred outcomes into one circle, and it changes nothing about fairness. A 3.6° sliver on a 100-entry wheel is exactly as likely as a 180° half-circle on a 2-entry wheel of equals, because the pick is made from random bytes before any geometry is involved. If you need a big-range number more often than a spectacle, a glance at the result line after a reduced-motion spin gives it instantly. The table shows several sizes of this preset side by side; the segment geometry guide covers the colour cycle and the boundary arithmetic in full.
| Range | Segments | Arc per segment | Chance per number |
|---|---|---|---|
| 1–2 | 2 | 180° | 50% |
| 1–6 | 6 | 60° | 16.67% |
| 1–10 | 10 | 36° | 10% |
| 1–12 | 12 | 30° | 8.33% |
| 1–20 | 20 | 18° | 5% |
| 1–25 | 25 | 14.4° | 4% |
| 1–50 | 50 | 7.2° | 2% |
| 1–100 | 100 | 3.6° | 1% |
The geometry also fixes where the pointer lands. On the default wheel the segment labelled 7 is index 6, starting 216° clockwise from the pointer and ending at 252°, with its midpoint at 234°. When 7 wins, the wheel is rotated so that the 234° midpoint rests under the pointer — the rotation is worked out from a winner that already exists, not the other way round.
One scripted spin, byte by byte
Scripted spin on 1–10. Feed the engine the bytes 250 then 6 and ask it to spin the default wheel. It asked the byte source 2 times: the first byte, once its excess top bits were masked away, landed at or beyond 10 and was discarded; the second was accepted and gave index 6, the number 7, with a landing angle of 234°. A remainder would have kept that first byte and assigned it a number. The engine never takes a remainder.
The mask is the other half of the mechanism. The engine takes the minimal number of bits whose range covers the segment count and ignores the rest of the byte, which you can see by feeding it two bytes that differ only in their top bits: bytes 6 and 246 both produce the number 7. The top bits never reach the comparison, so nothing about them can tilt the result. On a live spin the bytes come from the browser's cryptographically secure generator, the pick is made the instant you press Spin, and only then does the roughly four-second ease-out rotation begin — a rotation calculated to decelerate onto the segment that already won. If your system asks for reduced motion, the rotation is skipped and the identical draw is announced at once.
Modulo bias, demonstrated on this wheel
A single byte can hold 256 different values, and 256 cannot be shared equally
among 10 numbers. The naive way to map a byte onto the wheel — take the byte modulo
10 — hands the leftover values to the low numbers, which is the modulo bias the
methodology page describes. To show what the engine does instead, the build runs every one of the
256 byte values through uniformInt as the first byte of a spin, with a second
byte standing by in case of a redraw. The engine accepted 160 of them on the first
draw and rejected 96, drawing again for each. The 160 accepted
bytes fall on the 10 numbers exactly 16 times each — no number receives
a single extra byte. The redraws cost nothing but a fresh byte, and because the mask keeps the acceptance
rate above half, they are rare enough that spins stay instant. This is the same exhaustive check
the automated tests run.
Dealing 1–6 as turn order
Tick eliminator mode and the wheel stops answering "which number?" and starts dealing: each spin takes the number it lands on off the wheel, so spinning until the wheel is down to one hands out the whole range in random order with nothing repeated. For a table of 6 players numbered 1–6, read it as a turn-order deal — the first number removed plays first, the next removed plays second, and the one number that is never drawn, the survivor, plays last. Each spin is a fresh uniform draw over whatever is still waiting for a slot: 1/6 while all 6 are waiting, 1/5 once one has been seated, and so on until two are left. The deal below is driven by the scripted bytes 4, 7, 0, 3, 1, 0 so that the build can replay it; every cell, including which bytes each spin read, is the engine's own output.
| Spin | Waiting for a slot | Chance each | Bytes read | Drawn (index) | Plays |
|---|---|---|---|---|---|
| 1 | 1, 2, 3, 4, 5, 6 | 1/6 (16.67%) | 4 | 5 (4) | first |
| 2 | 1, 2, 3, 4, 6 | 1/5 (20%) | 7, 0 | 1 (0) | second |
| 3 | 2, 3, 4, 6 | 1/4 (25%) | 3 | 6 (3) | third |
| 4 | 2, 3, 4 | 1/3 (33.33%) | 1 | 3 (1) | fourth |
| 5 | 2, 4 | 1/2 (50%) | 0 | 2 (0) | fifth |
| — | 4 | — | none | 4 (never drawn — the survivor) | sixth |
Read down the last column and the seating falls out: 5 plays first, 1 plays second, 6 plays third, 3 plays fourth, 2 plays fifth, 4 plays sixth. Spin 2 is the row to study. With 5 numbers waiting, the engine read the byte 7, which after masking lands at or beyond those 5, so it threw the byte away and read 0 instead — 2 bytes for one pick, giving index 0 and the number 1. That is the same rejection rule that protects the full wheel, applied to a wheel that has shrunk. The survivor, 4, was never drawn at all; it is simply what remained when the wheel had nothing else to remove, and nothing about that makes the last slot special. Every spin is uniform over what is left, so each of the 6 numbers plays first with probability 1/6 and survives to play last with probability exactly 1/6, or 16.67%. A spin returns a fresh state instead of editing the old one, which is why the build can replay this deal from the same 6 bytes and print the same table. Two rules of the road follow. A one-number list cannot be dealt — the engine refuses with "Eliminator mode needs at least two entries." — and any edit to the list part-way through a deal starts it over on the edited list, so set the range before you seat anyone. Eliminator mode has its own guide, Eliminator mode, explained.
Custom sets: even numbers, steps and duplicates
Even numbers only. Paste 2, 4, 6, 8, 10, 12 as a single line. Because that
one line contains commas, the parser splits on the commas and trims each piece, giving 6 entries; the same 6 numbers on 6 separate lines parse to the
identical list, and the build checks that the two forms agree. The resulting wheel has
6 segments of 60° each, and every even number wins 16.67% of
spins. Pasting -2, -1, 0, 1, 2 works the same way and gives 5
entries — the engine does not care whether a label is a number, only that it fits on a segment.
Duplicates are the one custom-set trap worth naming. Type 7, 7, 8, 9 on 4 separate lines and the parser keeps all 4 entries, because two lines that read "7" are two entries; the number 7 then occupies 2 segments and wins 50% of spins. That is sometimes exactly what you want — a weighted list is the honest way to give one outcome a bigger share — but if it is an accident, tick Remove duplicate entries: the parser drops later copies case-insensitively, the list collapses to 3 numbers, and 7 is back to 33.33%. The caps are equally plain. A wheel holds at most 100 entries, and pasting 1 through 101 does not silently trim the last one: the engine refuses with "A wheel holds at most 100 entries — this list has 101. Remove some entries; nothing was silently dropped."
Sharing a range by link
Copy share link percent-encodes each entry and joins them with |
into a #items= fragment on this page's address. The even-numbers list above becomes
https://spinthatwheel.net/number-wheel/#items=2|4|6|8|10|12, which is 59 characters long, and the full 1–100 range encodes to 291 characters against a cap of 1800, so every range this preset can generate fits comfortably. Browsers do not include the
fragment in web requests: whoever opens the link has the identical wheel rebuilt locally, and
the list is never sent to the hosting server. Over-long lists get an honest error rather than
a truncated link, and a damaged link is reported as damaged.
Reading the result, and four misreadings
The winning number is drawn the instant you press Spin; the result line under the wheel announces it when the rotation settles — at once if your system asks for reduced motion — and the spin history below the list records recent results (the list is capped) until you clear it or close the tab. Four readings of that history are wrong, and each is wrong for the same reason: the pick comes from the bytes, not from the wheel. First, "it slowed right past 3, so 3 nearly won" — the rotation was calculated to stop on the winner, and no other segment was ever in contention. Second, "10 has not come up in a while, so it is due" — each spin is an independent draw at 10% on the 1–10 wheel, whatever came before. Third, "the thin slivers on 1–100 must win less often" — every sliver is 3.6° and wins 1% of spins, exactly like every other. Fourth, "eliminator mode changes the odds" — it changes what remains, and each remaining number stays exactly as likely as the others at every step. If you want to check any of this rather than take it on trust, the rigging guide walks through what to look for, and the browser's network tab will show that no request carries your list.
Related wheels
For the classic six-sided draw, the Dice Wheel is one press with no configuration. Letters instead of numbers live on the Letter Wheel, and a fifty-way geographic draw on the Wheel of US States.
Frequently asked questions
Is this better than "pick a number between 1 and 10"?
Much. People asked for a number between 1 and 10 disproportionately say 7, and almost never 1 or 10. The wheel gives each of the ten numbers exactly a 10% chance, drawn from cryptographic random bytes.
How do I change the range?
Type a maximum (2–100) into the "Numbers on the wheel" box and the list regenerates as 1 through your maximum. The list itself stays editable too — you can delete individual numbers or paste any custom set, like only even numbers.
What is modulo bias, and why does this wheel not have it?
The lazy way to make a random number — take a big random value and use its remainder — makes small numbers slightly more likely whenever the range does not divide evenly. This wheel instead draws just enough random bits and redraws whenever the value falls outside the range, so every number is exactly equally likely. The redraw loop is tested exhaustively.
Can I draw numbers without repeats, like a raffle?
Yes — eliminator mode removes each drawn number from the wheel, so spinning repeatedly deals out the range in random order with no repeats, exactly like pulling numbered balls from a bag.
Why does the range box refuse 1?
The box accepts a whole number from 2 to 100. A wheel with one number has nothing to decide, and eliminator mode refuses it outright — the engine answers "Eliminator mode needs at least two entries." A 2-number wheel is the smallest that can still surprise you: each number occupies 180° of the circle.
Can I use 0, negative numbers, decimals or steps of five?
Yes. The entries are text labels, so anything that fits on a segment is a valid entry. Pasting -2, -1, 0, 1, 2 on one line parses to 5 entries; 5, 10, 15, 20 parses to 4; 0.5, 1.5, 2.5 parses to 3; 2, 4, 6, 8, 10, 12 parses to 6. Type the set directly into the list instead of using the range box, which only generates 1 through your maximum.
Does a duplicate number get two chances?
Yes, and the wheel does not hide it: 2 segments labelled 7 are 2 separate outcomes. In the 4-line list 7, 7, 8, 9, the number 7 wins 50% of spins; tick "Remove duplicate entries" and the list collapses to 3 numbers, each at 33.33%.
Is a number "due" after a long run without it?
No. Each spin is an independent draw from fresh random bytes; nothing about previous spins, the wheel's resting position or the timing of your click reaches the pick. On the 1–10 wheel the chance is 10% on every spin, however the history reads. The history is a record, not a forecast.
Not for gambling: this is a fair randomizer for games and picks, not a certified drawing tool. Everything runs locally in your browser — see the methodology page.