💻 Coding

Random Number Generator

Generate unbiased random integers within a custom range using real cryptographic randomness.

Quick Presets:
0
Numbers Drawn
-
Min Value
-
Max Value
-
Mean (Average)

What Makes a Random Number Generator Unbiased?

An unbiased random number generator ensures every integer in the selected range has an identical mathematical probability of selection. Standard modulo arithmetic (% range) introduces modulo bias when the source bit space is not an exact multiple of the target range. Client-side cryptographic generators resolve this by applying rejection sampling over crypto.getRandomValues(), guaranteeing uniform statistical distribution.

Random Number Generation Engine Comparison

Method Cryptographic Security Modulo Bias Protection Execution Environment Primary Use Cases
crypto.getRandomValues() + Rejection Yes (CSPRNG) Complete (Zero bias) Client browser (WebCrypto API) Lottery, security tokens, fair raffles, gaming
Math.random() * (max - min) No (PRNG xoshiro128+) Prone to floating-point rounding Standard JavaScript engine Simple UI animations, non-critical casual shuffling
Linear Congruential (LCG) No (Predictable seed state) Moderate to High Legacy firmware & embedded C Legacy games, deterministic simulations
Hardware TRNG (Thermal/Atmospheric) Yes (Quantum/Physical noise) Complete with conditioning Specialized server hardware CA certificate generation, master cryptographic keys

About the Random Number Generator

Quick Answer: The Random Number Generator produces mathematically unbiased random integers within any custom minimum and maximum range using hardware-seeded Web Crypto API (crypto.getRandomValues) and rejection sampling. Features include unique number generation, bulk draws, live sorting, and complete client-side privacy.

Random integers are drawn from crypto.getRandomValues using rejection sampling, a technique that sidesteps the modulo bias a naive Math.random() * range calculation would quietly introduce. That keeps every value in your chosen range equally likely to come up, and you can choose whether repeats are allowed or every result has to be unique.

What modulo bias actually looks like with real numbers

Say you want a number from 1 to 10, and you generate it by pulling a random byte (0-255) and computing value % 10. That seems reasonable, but 256 is not evenly divisible by 10, it is 25 full groups of 10 plus 6 left over. That means the remainders 0 through 5 each occur 26 times across the 256 possible byte values, while remainders 6 through 9 only occur 25 times, a small but real, measurable skew toward the lower half of your range. It is subtle enough to go unnoticed in casual use, but it is a genuine statistical bias, not a rounding quirk, and it compounds the smaller your range is relative to the byte space you are drawing from.

How rejection sampling eliminates that bias entirely

Rather than accepting whatever value comes back and living with the skew, this tool first calculates the largest multiple of your requested range that still fits within the space of possible random values it draws (limit = maxValue - (maxValue % range)), then draws random bytes in a loop, discarding and redrawing any result that falls above that limit. Every value it actually accepts falls into one of an equal number of buckets, so the final result is genuinely, mathematically uniform across your range, with zero measurable bias, at the cost of occasionally needing to draw more than once, which happens rarely and is imperceptibly fast.

Why the number of random bytes pulled changes with your range

Rather than always drawing a fixed 4 bytes regardless of range size, this tool calculates the minimum number of bytes actually needed to comfortably cover your requested range using Math.ceil(Math.log2(range) / 8), a range of 1 to 100 needs just a single byte, while a range spanning millions needs several. Sizing the draw to match the actual range keeps the rejection rate low and the computation efficient regardless of whether you are picking a small dice-roll-sized range or a very wide one.

How uniqueness is guaranteed without risking an infinite loop

When "Allow duplicates" is off, the tool collects results into a JavaScript Set (which automatically ignores duplicate values) and keeps drawing until the set reaches your requested quantity. Before doing that, it explicitly checks whether your range even contains enough distinct numbers to satisfy the request, if you ask for 50 unique values from a range of only 20 possible numbers, it stops immediately with a clear error rather than looping forever trying to find 50 unique values that do not exist.

Why sorting uses an explicit comparator instead of the default

JavaScript built-in array .sort() defaults to comparing elements as strings, which produces famously wrong results for numbers, sorting [10, 2, 1] without a comparator gives you [1, 10, 2], since "10" sorts before "2" alphabetically. This tool explicitly passes (a, b) => a - b as the comparator when the Sort Results option is checked, forcing a genuine numeric ascending sort instead of falling into that well-known JavaScript pitfall.

Why Min and Max are validated before anything is generated

Before drawing a single random number, the tool checks that both values are numbers and that Min is not greater than Max, rejecting a backwards range immediately with a clear message rather than attempting to generate from a nonsensical range and producing a confusing downstream error. Min and Max being equal is allowed: it is a range of exactly one value, and asking for ten draws of it returns ten copies of that number rather than an error. This upfront validation, along with the separate duplicate-count check, means any failure you see points directly at what is actually wrong with your inputs rather than a generic error further down the process.

CSPRNG vs PRNG: The Internal Mechanics of Randomness

Computer software cannot generate true randomness without dedicated hardware peripherals. Instead, computational systems rely on pseudo-random number generators (PRNGs) or cryptographically secure pseudo-random number generators (CSPRNGs):

Operating System Entropy Pools: How WebCrypto Harnesses Physical Noise

When your browser executes crypto.getRandomValues(), it delegates generation directly to the underlying operating system kernel rather than computing numbers inside JavaScript memory:

The Coupon Collector Problem and Sampling Without Replacement

Generating a sequence of non-repeating random numbers is a fundamental problem in probability theory known as sampling without replacement. When choosing k unique integers from a pool of N numbers, two divergent computational strategies emerge:

For sparse selections where k is very small relative to N (e.g., drawing 5 lucky numbers from a range of 1,000), accumulating draws inside a hash set with rejection yields near O(1) performance because the probability of picking an already-seen number is negligible. However, as k approaches N, the probability of collisions escalates dramatically according to the Coupon Collector Problem, which dictates that collecting the final remaining values requires an expected N * ln(N) draws.

To avoid infinite redraw loops or severe execution delays when users request nearly the entire range, enterprise generators switch to a modern Durstenfeld-Knuth Fisher-Yates array shuffle. By pre-allocating the interval array and swapping elements in linear O(k) time, every permutation remains equally probable while execution finishes in fixed deterministic time.

Statistical Validation: Dieharder and NIST SP 800-22 Standards

To verify that random number generators do not suffer from hidden dimensional periodicity or non-uniform clustering, cryptographers subject algorithms to extensive empirical batteries:

Zero-Trust Architecture: 100 Percent Client-Side Execution

Utility369 enforces a strict client-first execution philosophy. Unlike server-rendered lottery utilities that harvest user queries or transmit lottery selections to third-party tracking databases, this Random Number Generator runs entirely inside your browser sandbox. You can disconnect your network cable or switch to airplane mode, and the WebCrypto rejection engine will continue operating with full mathematical fidelity.

Frequently Asked Questions

What exactly is modulo bias, in concrete terms?

If you generate a random byte (0-255) and compute value % 10 to get a number 1-10, remainders 0-5 occur 26 times across the 256 possible bytes while remainders 6-9 occur only 25 times, since 256 is not evenly divisible by 10. That is a real, measurable statistical skew toward the lower part of the range.

How does this tool avoid that bias?

It uses rejection sampling: it calculates the largest multiple of your range that fits the random values it draws, then discards and redraws any result falling outside that clean multiple. Every accepted value falls into an equally-sized bucket, producing a genuinely uniform result with zero measurable bias.

Why does the number of random bytes drawn change based on my range?

The tool calculates the minimum bytes needed to comfortably cover your specific range using a log2 calculation, rather than always pulling a fixed number of bytes. This keeps the rejection rate low and computation efficient whether your range is small or very large.

What happens if I ask for more unique numbers than my range contains?

The tool checks upfront whether your range has enough distinct values to satisfy the request. If not, for example asking for 50 unique numbers from a range of only 20, it shows a clear error immediately instead of looping forever trying to find values that do not exist.

Why does the Sort Results option need special handling?

JavaScript default array sort compares values as strings, which sorts numbers incorrectly, treating 10 as coming before 2. This tool explicitly uses a numeric comparator (a, b) => a - b when sorting is enabled, avoiding that well-known JavaScript pitfall.

Is this generator suitable for things like raffles or drawing lots?

Yes, since it draws from a cryptographically secure random source and eliminates modulo bias through rejection sampling, every number in your range has a genuinely equal chance of appearing, which is exactly what a fair drawing requires.

How does crypto.getRandomValues differ from standard Math.random()?

Math.random uses a deterministic pseudo-random algorithm (typically xoshiro128+ or XorShift128+) seeded with predictable system parameters, making its internal state mathematically reconstructible after observing several consecutive outputs. In contrast, crypto.getRandomValues interfaces directly with operating system entropy pools seeded by physical hardware noise.

Can this random number generator be used for cryptographic key generation?

Yes, the underlying entropy comes directly from WebCrypto crypto.getRandomValues, which qualifies as a cryptographically secure pseudo-random number generator (CSPRNG). However, for raw cryptographic symmetric keys or initialization vectors, developers should directly export raw typed byte arrays rather than mapping through integer range conversions.

What algorithm is used to guarantee non-repeating selections without performance degradation?

For draws where duplicates are disabled, the engine accumulates unique integers within an optimized JavaScript Set hash table. For small draws from large intervals, rejection addition has near O(1) performance. When drawing large subsets approaching the total range size, a Fisher-Yates shuffle over a pre-allocated array avoids the coupon collector slowdown.

Are generated random numbers logged or transmitted over the internet?

No. All random number generation and rejection sampling routines execute entirely in client-side memory within your local browser sandbox. No parameters, seed states, or generated integers are ever logged, cached, or transmitted across external networks.