Math.random() is not random. It's a deterministic algorithm that produces numbers that look random but are entirely predictable if you know the internal state. This distinction matters for security, simulation accuracy, and statistical validity.
Pseudorandom vs truly random
A pseudorandom number generator (PRNG) takes a seed value and produces a sequence of numbers through a deterministic algorithm. Given the same seed, it produces the same sequence every time. JavaScript's Math.random() uses xorshift128+ in V8 (Chrome/Node), which has a period of 2^128 - 1. That means after 2^128 - 1 numbers, the sequence repeats.
A truly random number generator uses physical entropy sources: thermal noise, radioactive decay, atmospheric noise, or the timing of hardware interrupts. These are fundamentally unpredictable because they're based on quantum-mechanical processes.
For most programming tasks, Math.random() is fine. For cryptography, authentication tokens, or anything security-sensitive, you need crypto.getRandomValues(), which draws from the operating system's entropy pool.
The counter pattern
A random counter combines counting with randomness. Instead of incrementing by 1 each time (1, 2, 3, 4...), you increment by a random amount within a range. This produces a monotonically increasing sequence with unpredictable gaps.
Use cases:
- Order numbers: Sequential but not guessable. If order #1001 is followed by #1007, an attacker can't enumerate orders by trying #1002 through #1006.
- Ticket numbers: Customers can't estimate how many tickets exist based on their ticket number.
- ID generation: UUIDs solve this differently, but random counters can produce shorter, more human-friendly identifiers.
Implementation
class RandomCounter {
constructor(start = 0, minStep = 1, maxStep = 10) {
this.value = start;
this.minStep = minStep;
this.maxStep = maxStep;
}
next() {
const step = this.minStep +
Math.floor(Math.random() * (this.maxStep - this.minStep + 1));
this.value += step;
return this.value;
}
}
const counter = new RandomCounter(1000, 1, 5);
// Produces: 1002, 1006, 1007, 1011, 1014...
The min and max step parameters control the density. A min of 1 and max of 100 produces sparse sequences. A min of 1 and max of 3 produces dense sequences with slight irregularity.
Statistical properties
A random counter's values follow a predictable distribution despite the randomness. After n increments with uniform random steps between min and max, the expected value is start + n * (min + max) / 2. The variance is n * (max - min)^2 / 12.
This means you can estimate the total count from the current value, but with increasing uncertainty. After 1,000 increments with steps between 1 and 10, the expected value is 5,500, but the standard deviation is about 91, so the actual value could reasonably be anywhere from 5,200 to 5,800.
I built a random counter tool at zovo.one/free-tools/random-counter that lets you configure the step range, starting value, and generation method. It's useful for generating non-sequential IDs, testing, and understanding how randomized counting works.
I'm Michael Lip. I build free developer tools at zovo.one. 500+ tools, all private, all free.
Top comments (0)