> random number generator <
// Generate cryptographically random integers and decimals — or seed it for reproducible runs
Cryptographic Randomness
Defaults to crypto.getRandomValues() with rejection sampling so every integer in your range is equally likely — zero modulo bias.
Reproducible Seeded Mode
Provide any seed string to switch to a deterministic mulberry32 PRNG. Same seed, same numbers — perfect for tests and simulations.
No Duplicates Mode
Generate unique integers via Fisher-Yates style sampling. Great for lottery picks, raffle draws, or sampling without replacement.
Decimal Precision Control
Switch to decimal mode and choose 1–10 places. Numbers are uniformly distributed across [min, max) and rounded to your chosen precision.
// ABOUT RANDOM NUMBER GENERATION
How It Works:
When the seed field is empty this tool calls crypto.getRandomValues(new Uint32Array(1)), a CSPRNG (Cryptographically Secure PRNG) backed by your operating system's entropy pool. To map a 32-bit unsigned integer onto an arbitrary [min, max] range without modulo bias the generator uses rejection sampling: any draw above the largest multiple of the range that fits in 2^32 is discarded and re-rolled. When you supply a seed, the string is hashed with cyrb53 to a 32-bit integer and fed into mulberry32, a fast 32-bit PRNG with a 2^32 period — deterministic and reproducible. Decimal mode scales a uniform [0,1) sample into [min, max), then formats with toFixed(places).
Example:
min=1, max=100, count=5, seed="hello" -> 39, 98, 64, 12, 71 (always)
Standards & References:
- >Web Crypto API (W3C) —
crypto.getRandomValues()contract for CSPRNGs - >RFC 4086 — Randomness Requirements for Security
- >mulberry32 — 32-bit PRNG by Tommy Ettinger, public domain
- >cyrb53 — fast 53-bit string hash for seeding (bryc, public domain)
Common Use Cases:
- >Lottery and raffle draws with provably unique picks
- >Random sampling without replacement for surveys and audits
- >Monte Carlo simulations and statistical experiments
- >A/B test bucketing with reproducible seeded assignments
- >Game mechanics: dice substitutes, loot tables, level seeds
- >QA test data and fuzzing input generation
- >Picking winners, judges, or first-presenters in meetings
- >Synthetic data generation for prototypes and demos
Related Tools:
- >UUID Generator — random v4 identifiers when you need a unique ID rather than a number
- >Password Generator — cryptographically random strings with character pool control
- >BIP39 Generator — random mnemonic seed phrases for crypto wallets
- >randompickerwheel.app — spinning-wheel UI when you want a visual random picker for a live audience or kids' classroom
// EXAMPLE OUTPUTS
Lottery draw — 6 unique numbers from 1-49
min=1, max=49, count=6, no-duplicates=on, sort=ascending
output:
7, 13, 22, 28, 35, 41
Dice substitute — ten d20 rolls (duplicates allowed)
min=1, max=20, count=10, no-duplicates=off, sort=none
output:
14, 3, 20, 11, 7, 14, 2, 19, 8, 11
Decimal sampling — 5 floats in [0, 1) with 4 decimal places
type=decimal, min=0, max=1, count=5, places=4
output:
0.4172, 0.8635, 0.0291, 0.5508, 0.7723
Seeded reproducible — same seed yields same sequence
min=1, max=100, count=5, seed="hello" (run twice)
output:
Run 1: 39, 98, 64, 12, 71 / Run 2: 39, 98, 64, 12, 71
Bucketing — 100 weighted A/B picks via integer mod
min=0, max=99, count=100, seed="experiment-42", sort=ascending
output:
0, 1, 3, 4, 7, 9, 12, ... 95, 97, 98, 99 (deterministic)
// IMPLEMENT IT YOURSELF
If you'd rather drop the algorithm directly into your own project, here are the three primitives this tool is built on. Together they cover unbiased cryptographic integers, deterministic seeded streams, and turning an arbitrary string seed into a 32-bit PRNG state. All public domain or MIT-equivalent.
Cryptographically secure integer in [min, max] (no modulo bias)
function secureRandomInt(min, max) {
const range = max - min + 1;
const buf = new Uint32Array(1);
const max32 = 0xFFFFFFFF;
const limit = Math.floor((max32 + 1) / range) * range;
let v;
do {
crypto.getRandomValues(buf);
v = buf[0];
} while (v >= limit);
return min + (v % range);
}
mulberry32 — deterministic seeded PRNG (32-bit state, ~2^32 period)
function mulberry32(seed) {
let a = seed >>> 0;
return function () {
a = (a + 0x6D2B79F5) | 0;
let t = a;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
// usage: const rng = mulberry32(0xC0FFEE);
// rng(); // 0.6743..., reproducible across runs
cyrb53 — fast string-to-32bit hash (use to seed mulberry32)
function cyrb53(str, seed) {
seed = seed || 0;
let h1 = 0xdeadbeef ^ seed;
let h2 = 0x41c6ce57 ^ seed;
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
Math.imul(h2 ^ (h2 >>> 13), 3266489909);
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return (h1 >>> 0);
}
// const rng = mulberry32(cyrb53('my-seed-string'));
// COMMON PITFALLS
> Modulo bias
Naive Math.floor(Math.random() * range) distributes the high bits unevenly when the range is not a power of two — some outputs land slightly more often than others. Use rejection sampling (the snippet above) to discard out-of-range draws and keep the distribution uniform.
> Math.random() is not cryptographically secure
Math.random() in V8/Spidermonkey uses xorshift128+, which is fast but predictable: an attacker who observes a few outputs can recover internal state and forecast future values. For tokens, salts, fairness-critical lottery draws, or anything an adversary cares about, always use crypto.getRandomValues().
> Seeded PRNGs are deterministic — never use them for security
Mulberry32 and friends are designed to repeat. That's exactly what you want for tests, simulations, and bucketing — and exactly what you don't want for password reset tokens or session IDs. If you find yourself piping a seed into anything user-facing or auth-adjacent, switch back to the CSPRNG immediately.
> Duplicate-rejection at high count exhausts capacity
Asking for k unique integers from a range of size n where k approaches n turns into a coupon-collector problem: the last few picks become exponentially expensive. This tool caps at 10,000 and uses Fisher-Yates partial sampling so capacity is exact, but a naive while-loop with seen.has(x) will hang silently when k > n. Always check capacity up front.
>> frequently asked questions
Q: Is this random number generator cryptographically secure?
A: Yes, by default. When you leave the SEED field empty the tool uses crypto.getRandomValues(), the Web Crypto API's CSPRNG, which on Linux/macOS reads from /dev/urandom and on Windows from BCryptGenRandom. We also apply rejection sampling so the mapping from a 32-bit integer to your custom range is unbiased. The output is suitable for security-adjacent tasks like generating tokens, choosing salts, or running fair lotteries. Note that supplying a seed switches to a deterministic PRNG (mulberry32), which is not cryptographically secure — use it only when reproducibility matters more than secrecy.
Q: What is the difference between seeded and unseeded mode?
A: Unseeded mode (default) uses your browser's CSPRNG and produces fresh, unpredictable numbers on every click — the same call will never return the same sequence twice. Seeded mode hashes the seed string into a 32-bit integer with cyrb53 and feeds it into mulberry32, a deterministic PRNG. Identical seed plus identical settings always yields the identical sequence, which is invaluable for reproducible experiments, debugging stochastic code, sharing test fixtures, or running A/B test bucketing where every user must always land in the same bucket.
Q: How does the no-duplicates option work?
A: For integers, no-duplicates draws from the range [min..max] using a Fisher-Yates inspired partial shuffle that yields the first k elements without ever repeating. We use a sparse swap map so memory usage stays O(count) rather than O(range), which means a draw of 10 unique numbers from 1 to 1,000,000 is just as cheap as 10 from 1 to 100. If you ask for more unique numbers than the range can supply (e.g. 20 unique integers in 1–10), the tool reports a clear capacity error rather than looping forever.
Q: Can I generate decimal (floating-point) random numbers?
A: Yes. Switch the TYPE radio to Decimal and pick a precision between 1 and 10 places. The generator draws a uniform float in [0, 1), scales it into [min, max), then rounds with toFixed(places) and parses back to a number. Note that max is exclusive in decimal mode (a side-effect of how floating-point uniformity is defined). For most statistical uses 4–6 decimal places is plenty; ten places approaches the limit of IEEE 754 double precision for typical small ranges.
Q: Is there a maximum count?
A: The count is capped at 10,000 numbers per click. That keeps the page responsive on phones and avoids edge-case browser behaviour around extremely large textareas. If you need millions of values, run multiple batches with different seeds and concatenate the output, or copy the algorithm into a Node script — the same mulberry32 / cyrb53 pair works server-side too. For UX reasons we sort, copy, and download all happen client-side, so 10k is a sensible ceiling that still finishes in well under a millisecond on a modern laptop.
Q: Is my data uploaded anywhere?
A: No. Every operation runs in your browser as plain JavaScript: number generation, sorting, statistics, copying to clipboard, and downloading the .txt file. No request is sent to our servers when you click GENERATE, COPY, or DOWNLOAD — you can verify with your browser's Network tab. We don't log seeds, ranges, or outputs. The page is static HTML served over HTTPS from a CDN, so nothing about your input is ever observable to us. This makes the tool safe for confidential test fixtures, internal lottery seeds, or anything else you'd rather keep off third-party servers.
Q: Can I avoid duplicates when generating decimal numbers?
A: Yes, the no-duplicates checkbox also applies to decimals using a best-effort retry loop. Because two independently sampled floats almost never collide at the bit level, duplicates are rare unless your range is tiny relative to the precision (e.g. min=0, max=1, places=2 only has 100 distinct values). If the loop can't find enough unique values within a reasonable number of attempts, the tool reports a capacity error so you can widen the range or increase the precision. For strict guaranteed-unique decimals, prefer integer mode and divide the result yourself.
Q: When should I use a spinning wheel instead of a number list?
A: A list of numbers is best for batch tasks: drawing 50 lottery tickets, generating test data, or feeding a simulation. A spinning wheel is better when one person picks one item in front of an audience and you want the suspense and visual payoff — classroom name picks, livestream giveaways, kids' chore rotations, decision-making meetings. If that's your use case, see randompickerwheel.app, which provides an interactive spinning-wheel UI built for that exact moment. Both tools draw from the same CSPRNG primitive — the difference is presentation, not fairness.