Random Number Generator — RNG, Integer & Decimal Picker
Pick one number, draw a lottery sample, or generate a unique-only set for raffles and bracket draws — all from a single page that runs without a server. Set the minimum and maximum (negative numbers and reversed inputs are accepted), choose how many numbers you want (1 to 100), then optionally enforce uniqueness so the same value never repeats and sort the output for easier scanning. The default mode samples each number independently with replacement, which is what you want for dice-style rolls; toggling unique-only switches to a Fisher-Yates shuffle of the full range, which is what you want for lottery draws or assigning numbered tasks to team members.
About this tool
Numbers come from the browser's Web Crypto API (crypto.getRandomValues), the same cryptographically secure source used by password generators and TLS handshakes. Rejection sampling avoids the modulo bias that naive `random() % range` introduces — every value in your chosen range has exactly equal probability, even when the range size doesn't divide evenly into 2^32. The unique-only toggle uses an unbiased Fisher-Yates shuffle over the integer pool, which guarantees a true permutation rather than reroll-on-duplicate (slow and biased near the upper count). Negative ranges, reversed min/max, and quantities larger than the range are all handled gracefully — the tool swaps endpoints and clamps the count automatically. Use it for lottery picks, classroom raffles, randomized A/B test assignment, picking a winner from a list of contest entries, generating sample data, or just settling who pays for lunch.
- Cryptographic randomness via Web Crypto (no Math.random modulo bias)
- Custom min and max — accepts negative numbers and reversed inputs
- Generate 1 to 100 numbers per draw
- Unique-only mode using Fisher-Yates shuffle (true permutation)
- Auto-sort toggle for easier reading of long sequences
- One-click copy of comma-separated results to clipboard
- Auto-clamps quantity to the range size when uniqueness is enforced
- Works offline once loaded — no server roundtrip per draw
- Suitable for lotteries, raffles, bracket seeding, and random sampling
- Zero data collection — your inputs and results never leave the browser
Free. No signup. Your inputs stay in your browser. Ads via Google AdSense (consent required).
Frequently asked questions
Is this generator actually random — or is it just `Math.random()` under a fancier label?
It is not `Math.random()`. Every draw calls `crypto.getRandomValues()` from the W3C Web Cryptography API (Recommendation 26 January 2017), which pulls bytes from the operating-system entropy pool (Linux `/dev/urandom`, macOS Security framework, Windows `BCryptGenRandom`) — the same source modern password managers and TLS handshakes use. `Math.random()` is fast but is implemented in V8 (Chrome, Node, Edge) and SpiderMonkey (Firefox) as the xorshift128+ algorithm (Vigna 2014; V8 switched to it in v4.9.41 with Chrome 49 stable in March 2016, replacing MWC1616) — it passes the BigCrush statistical battery but is not cryptographically secure and would be the wrong primitive for a tool that issues lottery numbers, raffle picks, or session tokens.
What is "modulo bias" and why does it matter for fair draws?
Modulo bias is the small but systematic skew that appears when you take an integer from a uniform range and reduce it mod N where N does not divide the source range evenly. The underlying source here is a 32-bit unsigned integer (range 0..2³²−1). If you ask for a number in 1..100, naive `r % 100` gives every value in 0..95 a probability of 42,949,673 mappings out of 2³² and every value in 96..99 only 42,949,672 mappings — the lower numbers are slightly more likely. The per-low-value excess is 1/2³² ≈ 1 in 4.3 billion, invisible for a coin flip but cumulative across millions of draws (lottery-grade applications, security-token issuance). The fix is rejection sampling: draw, check whether the value falls in the largest multiple of N that fits, retry if not. This tool's `randInt(n)` does exactly that — the expected number of retries is bounded by 2 regardless of N, so the cost is negligible.
Why does the unique-only mode use Fisher-Yates instead of just re-rolling when it sees a duplicate?
Re-roll-on-duplicate (the obvious approach) becomes pathologically slow as the draw count approaches the range size — drawing the last few unique numbers from 1..100 requires on average about 519 draws for all 100 distinct (the coupon-collector limit, n · H_n ≈ 100 × 5.187) and biases the late draws because duplicates skew the empirical distribution. Fisher-Yates (Knuth's Algorithm P from the 1969 Art of Computer Programming Vol 2 §3.4.2, in-place adaptation by Durstenfeld CACM 1964 of the original Fisher & Yates 1938 pencil-and-paper procedure) generates a uniformly random permutation of the full pool in O(range) time and O(range) space, then takes the first N elements. Every permutation is equally likely, every unique-only result set is equally likely, and the runtime stays linear in the range size regardless of how many you draw.
Should I use this for a real lottery, sweepstake, or business-critical draw?
For low-stakes (raffle at the office, classroom seed assignment, A/B test bucket, picking a winner from a comment thread) this tool's `crypto.getRandomValues()` source is more than enough — same primitive RFC 4086 (Eastlake/Schiller/Crocker BCP 106 June 2005) recommends for non-adversarial cryptographic key generation. For regulated lotteries (state-licensed gaming, securities-trading random sampling, clinical-trial randomization) the rule is procedural, not statistical: regulators require an audit trail (logged seeds, witnessed draws, third-party hash chains) and a hardware RNG with periodic statistical testing (NIST SP 800-22, FIPS 140 module validation), neither of which a client-side browser tool can provide. Use this for everyday random picks; use a regulated audited service or a notarized physical draw for anything legally binding.
What about decimal random numbers, or numbers outside the 1..2³² range?
This tool generates integers only — that is what `randInt(maxExclusive)` produces from `crypto.getRandomValues()` plus rejection sampling. The internal cap is 2³² because the underlying entropy buffer is a Uint32Array; ranges up to about 4.29 billion work natively, beyond that you would need a multi-word draw which this tool does not expose. For floating-point random numbers in [0, 1) the `rand()` helper in `src/lib/random.ts` divides a Uint32 by 2³², giving 32 bits of fractional precision — enough for most simulations but not the full 53 bits of a JavaScript double (the workaround is `crypto.getRandomValues()` with a `BigUint64Array` for 64-bit doubles). Negative ranges, reversed `min/max`, and quantities larger than the integer range are handled by swapping endpoints and clamping the count automatically.
Sources (7)
- Knuth, D. E. (1997). The Art of Computer Programming, Volume 2: Seminumerical Algorithms — §3.4.2 Algorithm P (Shuffling) — the in-place O(n) shuffle that this tool uses for the unique-only mode; Knuth attributes the modern computer-friendly variant to Durstenfeld 1964 and acknowledges the original 1938 pencil-and-paper version by Fisher & Yates. Addison-Wesley, 3rd edition (1997, ISBN 0-201-89684-2); §3.4.2 Algorithm P first published in 1st edition 1969.
- Durstenfeld, R. (1964). Algorithm 235: Random permutation — the in-place computer-friendly shuffle that Knuth later named Algorithm P; iterates from the last element down, swapping each element with a uniformly chosen index in the unshuffled prefix; runs in O(n) time and O(1) extra space (vs Fisher & Yates 1938 original O(n²)). Communications of the ACM, Vol. 7, No. 7, p. 420 (July 1964).
- World Wide Web Consortium (W3C) (2017). Web Cryptography API — defines `crypto.getRandomValues()`, the cryptographically secure pseudo-random source used by this tool (and by password generators, TLS handshakes, and session-token issuers); fills a TypedArray with values from the operating-system entropy pool — fundamentally different from `Math.random()`, which V8 implements as xorshift128+ (since v4.9.41, Chrome 49 stable March 2016) and is not suitable for security-sensitive draws. W3C Recommendation 26 January 2017 (Crypto.getRandomValues §3.3); Web Cryptography API Level 2 in progress as of May 2026.
- Eastlake III, D., Schiller, J., & Crocker, S. (2005). RFC 4086 — Randomness Requirements for Security (BCP 106) — catalogs poor entropy sources (system uptime in seconds, low-resolution timers, clock skew alone) and pitfalls of weak PRNGs in security-sensitive contexts; obsoletes RFC 1750; recommended reading for any tool that issues lottery numbers, raffle picks, or session tokens. IETF Best Current Practice 106, June 2005; authors at Motorola Laboratories (Eastlake), MIT (Schiller), and Shinkuro Inc. (Crocker).
- Vigna, S. (2014). Further scramblings of Marsaglia's xorshift generators — introduced the xorshift128+ algorithm that V8 (Chrome, Node.js, Edge, Opera) and SpiderMonkey (Firefox) use to implement `Math.random()` since V8 v4.9.41; passes the BigCrush battery from TestU01 but does not pass all linearity tests (later shown by Lemire & O'Neill 2018) and is NOT cryptographically secure. Journal of Computational and Applied Mathematics 315 (May 2017) pp 175-181; pre-print arXiv:1404.0390 (April 2014, last revised 2016).
- National Institute of Standards and Technology (NIST) (2010). NIST SP 800-22 Revision 1a — A Statistical Test Suite for Random and Pseudorandom Number Generators for Cryptographic Applications — the test battery (frequency, runs, longest-run, rank, FFT, non-overlapping/overlapping templates, Maurer's universal, linear complexity, serial, approximate entropy, cumulative sums, random excursions) that regulators require periodic hardware-RNG products to pass; FIPS 140 module validation programs incorporate it. NIST Special Publication 800-22 Rev 1a, April 2010 (Bassham et al.); reaffirmed by NIST 2025.
- World Wide Web Consortium (W3C) (2018). Web Content Accessibility Guidelines (WCAG) 2.1 — Success Criterion 4.1.3 Status Messages requires that operations producing dynamic content (the generated number list, the running tally) expose changes via `aria-live` regions so assistive technology users hear updates without a focus shift. W3C Recommendation 5 June 2018; carried unchanged into WCAG 2.2 (Recommendation 5 October 2023).
These are the original publications the formulas in this tool are based on. Locate them by journal name and year on Google Scholar or PubMed.
By Marco B. ·