A number picker is a small program that returns one or more random integers from a range you define, with every integer in that range — including both endpoints — equally likely to appear. The picker offered here takes three inputs: a minimum integer, a maximum integer, and a result count between 1 and 1,000, then returns the integers as a comma-separated list you can copy. It runs entirely in your browser, draws its randomness from the Web Crypto interface, and uses rejection sampling to make sure each integer in the range has the same chance of being chosen rather than being biased by uneven modulo arithmetic. Both bounds may be negative, duplicates can be allowed or disallowed, and a request that cannot be satisfied (for example, five unique values from a range of three) is rejected up front with a clear error instead of looping or silently returning fewer numbers. This article walks through what the picker does, why the output is fair, and exactly how to use it.

number picker explained
Number Picker Explained: How Fair Random Integers Work

What a number picker actually does

The simplest way to think about a number picker is as a function f(min, max, count) returning a list of integers. You define an inclusive range [min, max], decide how many integers you want back, and the picker returns them. The word inclusive is doing real work: a range from 1 to 10 includes 1 and 10 as well as every integer in between, so any one of those ten values could be the result. If min and max are the same number, the only possible result is that number.

Two side controls shape what kind of list comes back. The result count tells the picker how many integers to produce, from 1 to 1,000 per run. The duplicate toggle changes the relationship between successive draws: with duplicates enabled, every draw is independent and the same number can appear several times in the output, which is what you want for repeated simulations or events where earlier results should remain eligible. With duplicates disabled, the picker guarantees that no integer in the list appears twice, which is what you want for selecting distinct positions, identifiers, or numbered participants.

Both bounds may be negative or straddle zero. The inclusive range still works the same way: from −5 to 5 means every integer from −5 through 5 is a candidate. The only constraint on the bounds is that they must be JavaScript safe integers, the largest range of whole numbers the browser can represent exactly. Any value outside that window cannot be mapped honestly, so the picker rejects it.

How the tool picks numbers without bias

A naive random number generator takes a raw random value and applies a remainder operation (modulo) to map it into a target range. That approach is biased whenever the source range is not an exact multiple of the target range: the leftover values in the incomplete tail get mapped to early outputs more often than to later ones. For a picker that needs every integer in a user-chosen range to be equally likely, that bias is unacceptable.

The picker sidesteps the problem with rejection sampling. The browser supplies raw 32-bit random words through the Web Crypto getRandomValues call, which are combined into a 53-bit nonnegative integer — the largest value JavaScript can hold exactly. The picker asks for a raw value from a window just large enough to cover the inclusive range, and discards any value that falls into the incomplete tail before mapping the accepted value to a specific integer in the range.

A concrete example makes the pattern clear. Suppose the inclusive range is 1 to 3, so the range size is 3. A 2-bit raw value can be 0, 1, 2, or 3. The largest multiple of 3 that fits below 4 is 3, so raw values 0, 1, and 2 are accepted and raw value 3 is rejected and redrawn. Mapping then sends 0 → 1, 1 → 2, and 2 → 3, giving each output exactly one accepted raw value and therefore an equal probability. The same logic scales to any safe-integer range: each integer in the inclusive range receives the same number of possible accepted raw values.

When the picker needs unique values with duplicates disabled, it does not build an array for every integer in a potentially huge range. Instead it uses a sparse partial Fisher-Yates shuffle that picks unique offsets in O(count) memory, which keeps the response fast even for very large ranges where only a handful of values are being requested.

Randomness itself comes from the browser's built-in Web Crypto interface rather than Math.random, which is not designed for cryptographic strength. The MDN reference for Crypto.getRandomValues is the authoritative description of how the browser exposes this source of entropy.

How to use the number picker

Open the Random Number Generator and set three inputs, then generate.

  1. Enter the minimum safe integer in the lower bound field and the maximum safe integer in the upper bound field. Both endpoints are eligible results, so a range from 1 to 10 can produce either 1 or 10.
  2. Choose a result count from 1 to 1,000, and decide whether duplicate numbers are allowed by leaving the duplicate setting on or turning it off.
  3. Select Generate numbers. The previous result list is cleared automatically whenever any input changes, so the list you see always matches the current settings.
  4. Review the comma-separated output, then select and copy it for use in your activity, dataset, or document.

For a unique randomized ordering of every integer in a small range, set the count equal to the number of integers in the range and disable duplicates. For repeated experiments, leave duplicates enabled and generate a new list whenever you need a fresh independent sample.

Settings and what they change

The four user-facing controls — minimum, maximum, count, and duplicates — interact in a small number of predictable ways. The table below summarizes the behavior you can expect from each combination.

SettingBehaviorBest for
Duplicates allowedIndependent draws; the same value may appear more than once in the output list.Repeated simulations, dice-like experiments, sampling with replacement.
Duplicates disabledEvery value in the output is unique; the picker will not return the same integer twice.Selecting distinct positions, drawing numbered participants, assigning unique IDs.
Count = 1A single integer is returned.Quick decisions, 50/50 style choices (range of two), one-shot draws.
Count = range size with duplicates offA permutation of every integer in the range, in random order.Randomized ordering of every value in a small range.
Count larger than range size with duplicates offRequest is rejected with a clear error before any draw happens.Impossible unique requests are caught up front instead of looping or silently truncating.

The combination you pick changes only the output, never the underlying randomness: every accepted raw value is still equally likely regardless of count or duplicate preference.

When a number picker is the right tool — and when it isn't

Number pickers are well suited to ordinary tasks that need unpredictable whole numbers: classroom activities, drawings, randomized test data, order selection, and game setup. Because the tool runs locally and never uploads them, your bounds and results stay private to the current browser tab and do not leave your machine.

The picker is not a substitute for an audited lottery, gambling, or cryptographic-key system. It does not publish a seed, signed transcript, external randomness beacon, or reproducible audit trail, and a visitor cannot later prove which browser entropy produced a particular list. For regulated prize drawings, access control, passwords, tokens, or any consequential decision, follow the independently audited procedures required by your organization rather than relying on a generic browser tool.

For specialized contexts — scripting languages, spreadsheets, command-line work, or programmatic APIs — the same assignment may be solved differently. A practical reference for the inputs, limits, and settings of this picker is collected in the Number Picker cheat sheet, which complements this conceptual walkthrough with a quick lookup.

Input limits and the errors you can see

Inputs are bounded for two practical reasons: the browser cannot represent every integer exactly, and silent rounding would make a request look successful when its bounds are not what was intended. The picker enforces a small set of explicit limits.

  • Both bounds and the inclusive range size must be JavaScript safe integers. Larger numeric text cannot always be represented exactly by the browser, so values outside that window are rejected.
  • Reversed bounds (a maximum below the minimum) are rejected, as are blank fields, decimal values, infinity, and other non-integer entries.
  • A unique request whose count exceeds the size of the inclusive range is rejected with a clear error. Five unique values from 1 through 3 cannot be done because the range only contains three integers.
  • Each operation returns at most 1,000 integers. This cap prevents accidental memory-heavy requests and keeps errors visible rather than letting the tool quietly hand back a truncated list.

If you need arbitrary-precision values wider than the safe-integer range — for example, cryptographic-size numbers — use a specialist system that accepts integer strings rather than ordinary browser numbers. For every other ordinary request, the constraints keep the picker predictable and the errors obvious.

Related reading: Dice Roller D100: Roll a Fair 1–100 in Your Browser.