Math & Scientific
Generate Random Numbers in JavaScript with Checked Bounds
Use Math.random for ordinary random values, write a checked inclusive-integer helper, and test its boundaries without confusing pseudorandomness with security.
Start with the value Math.random actually returns
Math.random() returns a floating-point value greater than or equal to zero and less than one. It does not directly return a die roll, percentage or integer in an arbitrary interval. Scale and shift that value to match the intended range. For ordinary nonsecurity examples, Math.random() × 10 produces a floating-point value on the zero-to-ten scale, while Math.floor(Math.random() × 6) + 1 produces an integer from 1 through 6. Keep floating-point output and integer output separate in the function name or documentation so that callers know what to expect.
Define an inclusive-integer helper with explicit validation
The helper below accepts numeric safe-integer endpoints and includes both of them in the result. It checks that the maximum is not smaller than the minimum and that the inclusive span fits its supported exact-integer arithmetic. Numeric strings are deliberately rejected; callers should validate and convert external input separately. A range containing just one integer is valid and always returns that integer. This function is meant for ordinary examples and simulations, not secret generation. Its checks avoid silently accepting enormous integers that JavaScript has already rounded.
function randomIntInclusive(min, max) {
if (!Number.isSafeInteger(min) || !Number.isSafeInteger(max)) {
throw new RangeError("Use safe-integer endpoints");
}
if (max < min) {
throw new RangeError("Maximum must be at least minimum");
}
const span = max - min + 1;
if (!Number.isSafeInteger(span)) {
throw new RangeError("The inclusive range is too wide");
}
return Math.floor(Math.random() * span) + min;
}Check small examples before using a larger interval
randomIntInclusive(1, 6) returns one of the six die-face integers. randomIntInclusive(-3, 3) permits seven results, including zero. randomIntInclusive(7, 7) always returns 7. For a positive six-digit number, use 100000 and 999999 as the endpoints; using zero as the minimum would also permit shorter numerical values. The helper returns a number, not a fixed-width text identifier. If leading zeros matter, perform a separate formatting step after validating the intended numeric range rather than expecting numeric arithmetic to preserve them.
Use floor rather than round for the integer mapping
For a six-face die, floor(u × 6) divides the source interval into six equal-width regions before adding 1. Using round(u × 5) + 1 instead gives narrower source regions to the endpoints than to the interior values. That changes the intended selection behavior. Similarly, forgetting the +1 in an inclusive span prevents the documented upper integer from being selected by the usual floor formula. Floating-point random generation is still approximate; avoid presenting a small observed frequency table as proof that an implementation is perfectly uniform.
Test boundary behavior without relying on luck
A useful test supplies controlled source values such as zero and a representable value just below one. For the 1-through-6 example, those should map to 1 and 6. Also test equal endpoints, negative bounds, reversed bounds, fractional inputs and integers outside the safe range. In an isolated test environment, a controlled random function or a temporary Math.random replacement can make those cases reproducible; restore any replaced global function afterward. Repeatedly running a random test until the expected endpoint happens to appear is slower and can leave a broken boundary untested.
Separate sampling, uniqueness and reproducibility
Calling the helper several times samples with replacement, so repeated integers are allowed. If you need a random ordering of a known finite list, use a suitable shuffle or without-replacement selection instead of assuming repeated calls will stay unique. If a test must reproduce an entire random sequence, use a generator with an explicitly controlled seed and record that seed; the built-in Math.random API does not expose one. Saving a fixed fixture list is another option for a regression test that needs identical inputs every time rather than new random coverage.
Choose the correct security boundary and local tool
MDN states that Math.random is not cryptographically secure and points to the Web Crypto API for cryptographic random values. Secure tokens require a design appropriate to their format and use; the integer helper here is not such a design. The linked Random Number Generator lets you try an ordinary inclusive range and a count without writing code, using the same class of noncryptographic randomness. It allows repeats, rejects unsupported integer ranges and has no seed or replay option. Use the form for numerical examples and the checked helper when its stated assumptions match your JavaScript application.