Skip to main content

Random Number Generator

Generate random numbers within a range with options for uniqueness and sorting.

Reviewed by · Last reviewed

to
(1 - 1000)

Using the Random Number Generator

  1. Set the Min and Max inputs to define an inclusive range. Negative numbers and decimals are both accepted.
  2. Choose how many numbers to generate with the Count input, from 1 up to 1000. The control is just a numeric field, so you can paste large counts rather than holding a button.
  3. Toggle the option checkboxes: Allow duplicates permits repeats, Sort results orders the output ascending, and Integers only restricts to whole numbers rather than floats.
  4. Press Generate. The result grid fills immediately; each number is its own cell so you can copy a single value with a click, or use the Copy All button for a comma-separated dump.
  5. Regenerate as often as you want. The tool pulls fresh entropy each time, so consecutive runs will not repeat.

Which Random Source Is Used

The tool uses crypto.getRandomValues, the cryptographically secure interface exposed by the Web Crypto API on every modern browser. For integer output it asks for a Uint32Array, then maps each 32-bit value into the target range using rejection sampling to avoid modulo bias. For float output it calls getRandomValues on a Uint32Array and converts to a uniformly distributed float in [0, 1) by dividing by 232, which preserves uniformity better than the common Math.random()-based shortcut.

The distinction matters. Math.random() in V8 uses an xorshift128+ PRNG seeded at tab creation; it is fine for casual games and UI shuffles but emits predictable sequences once a few outputs are known, and its uniformity over large ranges is weaker than a proper cryptographic source. crypto.getRandomValues routes to the operating system CSPRNG (on Linux, getrandom(2); on macOS, /dev/urandom; on Windows, BCryptGenRandom) and is suitable for token generation, sampling without predictability, and anything where an adversary might observe outputs. The entire generation runs client-side; nothing is sent to a server.

Real Tasks This Is Useful For

  • Picking a raffle or giveaway winner from a numbered list of entries.
  • Seeding a test fixture with reproducible-looking data that is actually unpredictable.
  • Generating a short set of non-duplicate lottery numbers for a casual pool.
  • Building a shuffled sample for QA - for example 20 order IDs out of a larger range to spot-check.
  • Producing a random tick schedule for a load test that should not be on round intervals.
  • Making up test salaries, ages, or prices for a UI mockup without leaking real data.

Common Pitfalls

  • Modulo bias. Naive code that maps a 32-bit random value with value % range over-represents the lower end when range does not divide 232 evenly. The tool rejects out-of-band draws instead, which is slower on paper but imperceptible in practice.
  • Duplicates when you did not want them. Uncheck Allow duplicates. The tool will then error if your count exceeds the available distinct integers in the range.
  • Float precision. Floats use IEEE 754 binary64, so not every decimal value in your range is representable. Two calls might land on the same nominal decimal by rounding.
  • Range boundaries. Both Min and Max are inclusive. If you want half-open behaviour like most programming libraries (for example Python's range), subtract 1 from your Max.
  • Sorting hides duplicates. With Sort results on and Allow duplicates on, identical values end up adjacent and are easy to miss at a glance; scan before interpreting.
  • Very large counts (close to 1000) with unique-only mode and a small range can take a visible moment because the rejection-sampling loop has to avoid already-drawn values.

What "Random" Actually Means Here

A random number source has two properties that matter: uniformity (every value in the range is equally likely) and unpredictability (future outputs cannot be inferred from past ones, even with unlimited compute). Math.random() delivers the first but not the second; a CSPRNG delivers both. The NIST SP 800-90A and 800-90B documents define the standard for cryptographic DRBGs, and crypto.getRandomValues is specified against that standard by the W3C Web Cryptography API (TR 2017, last significant revision 2024). For dice, cards, and everyday shuffling the difference is invisible; for anything that could plausibly be attacked - session tokens, one-time passwords, game seeds where an adversary gains from prediction - the difference is critical.

Alternatives and Tradeoffs

Command-line alternatives include shuf -i 1-100 -n 10 for a shuffled sample (GNU coreutils), jot -r 10 1 100 on macOS and BSDs, Python's secrets.choice and random.sample, and openssl rand for raw bytes. For reproducible-with-a-seed generation you want numpy.random.default_rng(seed) or Julia's Random.MersenneTwister(seed); this tool deliberately does not expose a seed because seeding a CSPRNG defeats its purpose. Spreadsheets have RAND and RANDBETWEEN, both based on engine-specific PRNGs that should not be trusted for anything adversarial. Dedicated hardware sources (HRNGs) like Intel RDRAND or the ID Quantique quantum RNG are overkill for non-cryptographic applications but exist when you need a certified entropy source.

Frequently Asked Questions

Is this suitable for cryptographic use like generating tokens?

For generating session tokens, API keys, or password-reset nonces the underlying source (<code>crypto.getRandomValues</code>) is appropriate - it is the same CSPRNG you would use in a dedicated library. However, for production you typically want to generate those tokens server-side where length, alphabet, and rate-limit controls can be enforced. This tool is fine for a throwaway test key or a one-off demo, but it is not an auditable token mint.

What is the difference between Math.random() and crypto.getRandomValues?

<code>Math.random()</code> is a non-cryptographic pseudo-random generator (xorshift128+ in V8, xorshift in SpiderMonkey, a SIMD-friendly variant in JavaScriptCore). It is deterministic once seeded and its future outputs can be predicted by an adversary who has observed enough prior outputs. <code>crypto.getRandomValues</code> is backed by the operating system CSPRNG and is designed to be indistinguishable from true randomness even to an observer with unbounded compute. This tool uses the latter.

Does the page send my range or count to any server?

No. The entire generator runs in a Preact island loaded with <code>client:load</code>. The <code>crypto.getRandomValues</code> call is a synchronous local API that never touches the network, and the UI does not POST your inputs anywhere. Check the DevTools Network tab during a generation to confirm - zero outbound requests.

What happens if I ask for more unique integers than the range allows?

The tool detects the impossibility (count &gt; max - min + 1 under <em>Allow duplicates</em> off) and flags it before generating. Rather than silently duplicating or hanging in an infinite rejection loop, you get an immediate validation message. Widen the range or enable duplicates to proceed.

How does the tool avoid modulo bias?

Naively computing <code>rawU32 % range</code> slightly overrepresents the smaller values because 2<sup>32</sup> almost never divides a user-supplied range evenly. The tool computes the largest multiple of <code>range</code> below 2<sup>32</sup>, rejects any draw above that threshold, and retries. The rejection probability is at most <code>range / 2</code><sup>32</sup>, which for any realistic range is well under one in a million.

Can I get reproducible results with a seed?

No, and that is a deliberate design choice. A CSPRNG seeded with a known value is no longer cryptographically secure because an observer with the seed can replay all outputs. If you need reproducibility for testing or simulation, use a seedable PRNG library like seedrandom.js, numpy, or <code>Math.seedrandom</code>, and accept that it is not cryptographically strong.

How uniform is the floating-point output?

Very uniform. The tool reads a 32-bit unsigned integer, divides by 2<sup>32</sup> to get a value in [0, 1), then scales to the target range. The spacing between representable outputs in [0, 1) is therefore 2<sup>-32</sup>, which is much finer than the visible six-decimal display. Every value in the range has the same probability to within 2<sup>-32</sup>.

Why does sorting interact with duplicates?

If both options are on, duplicates land adjacent after sorting and can look like a display bug. They are not - both are real outputs and the frequency is correct in expectation. If you want to tell duplicates from singletons, either sort first and scan, or leave duplicates off and let the uniqueness guarantee do the work.

What is the maximum count and why?

The tool caps at 1000 numbers per generation. Each draw costs either 4 bytes of entropy (for integers) or one 32-bit read plus a division (for floats), so the hard compute limit is much higher, but 1000 is the point where the output pane stops being scannable. For very large datasets use a scripting language where you can stream to a file.

Is the generator fair for very small ranges?

Yes. For a range of size 2 the rejection-sampling loop effectively reads a single bit and is perfectly uniform. For a range of size 6 (a dice-sized range), the bias in a na&iuml;ve modulo approach would be about 4 parts in 2<sup>32</sup>, which is irrelevant for gameplay but the rejection-sampling path eliminates even that much. See the dedicated Dice Roller page for a tabletop-focused variant.

More Math & Calculators