Generators
How to Generate Random Numbers in a Range (Unique, Sorted, and Fair)
A practical guide to generating random numbers in any range, drawing unique values without repeats, and avoiding common off-by-one and bias mistakes.
Try the toolRandom Number Generator →The problem: 'just give me a random number' is harder than it looks
You need to pick a raffle winner, sample rows for a test, roll dice for a game, or seed some fixtures. It sounds trivial, but the moment you add constraints — a specific range, no duplicates, sorted output — the naive approaches start producing subtle bugs: off-by-one errors that never emit the top value, or a loop that occasionally returns the same "unique" number twice. Getting random numbers right is mostly about being precise with the boundaries and the rules.
How random ranges work
Most languages give you a raw random float in the half-open interval [0, 1) — zero is possible, one is not. To map that onto an integer range you scale and floor it. The standard formula for an inclusive range from min to max is:
function randomInt(min, max) {
// both min and max are inclusive
return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6); // a fair dice roll: 1,2,3,4,5,6
randomInt(0, 100); // any integer 0 through 100The + 1 is the detail everyone forgets. Without it you can never roll a 6, because Math.random() never reaches 1. That single missing character is the most common random-number bug there is.
Unique draws and sorting
"Give me 5 unique numbers between 1 and 50" is a different problem: you are sampling without replacement. Rejection sampling (generate, discard duplicates, repeat) works but degrades badly when you need most of the range. A cleaner approach is to shuffle the candidates and take a slice:
function uniqueSample(min, max, count) {
const pool = [];
for (let n = min; n <= max; n++) pool.push(n);
// Fisher-Yates shuffle
for (let i = pool.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[pool[i], pool[j]] = [pool[j], pool[i]];
}
return pool.slice(0, count);
}
uniqueSample(1, 50, 5).sort((a, b) => a - b);
// e.g. [7, 12, 28, 41, 49] -- guaranteed no repeatsThe Random Number Generator does all of this for you: set the minimum and maximum, choose how many values you want, toggle unique to forbid repeats, and optionally return the results sorted. It runs entirely in your browser, so it is fast and nothing leaves your machine.
Common pitfalls
- Off-by-one at the boundaries. Decide up front whether
maxis inclusive and make the formula match. Inclusive is what most people expect. - Asking for more unique numbers than the range holds. You cannot draw 10 unique values from 1–5. A good generator caps the count at the range size.
- Confusing unpredictable with fair.
Math.random()is fine for games, sampling, and test data, but it is not cryptographically secure. Never use it for tokens, passwords, or anything security-sensitive. - Modulo bias. Using
rawInt % rangeto squeeze a big random integer into a small range skews the distribution slightly toward lower values. The scale-and-floor formula above avoids it.
When you need security instead of randomness
If the number is a secret — a session token, a one-time code, an unguessable identifier — you want a cryptographically secure source, not a statistical one. For those cases reach for the Password Generator or generate an unguessable ID with the UUID Generator, both of which draw on secure randomness.
Conclusion
Generating random numbers well is a matter of precision: nail the inclusive-or-exclusive boundary, use shuffle-and-slice when you need uniqueness, sort only when order matters, and never reach for plain statistical randomness when a secret is on the line. Set your range, pick your options, and let the tool handle the edge cases so your raffle, sample, or dice roll comes out fair every time.