- Stage 1
- Authors: WhosyVox and Tab Atkins-Bittner
- Champions: Tab Atkins-Bittner
- Spec Text: currently this README
Historically, JS has offered a very simple API for randomness: a Math.random()
function that returns a random value from a uniform distribution in the range [0,1), with no further details. This is a perfectly adequate primitive, but most actual applications end up having to wrap this into other functions to do something useful, such as obtaining random integers in a particular range, or sampling a normal distribution. While it's not hard to write many of these utility functions, doing so correctly can be non-trivial: off-by-one errors are easy to hit even in simple "simulate a die roll" cases.
This proposal aims to add a handful of new simple uniform-distribution random number methods. (At the request of the committee, further use-cases are being offloaded to separate proposals, notably Random Collection Functions and Random Distributions.)
This proposal builds on the (now Stage 2) Seeded Random proposal, which adds a new Random
namespace object, both to host the Random.Seeded
class itself and to host the Random.Seeded
random methods, so you can call them with a randomly-seeded PRNG created by the User Agent rather than always having to create a Random.Seeded
yourself.
There is a very large family of functions we could potentially include. This proposal is intentionally pared down to the basic set of commonly-written random number functions: random numbers in a range other than 0-1, random integers, random bigints, and random bytes, all drawn from a uniform distribution.
If step
is omitted,
returns a random Number
in the range (lo, hi)
(that is, not containing either lo
or hi
)
with a uniform distribution.
(If there are no floats between lo
and hi
,
returns lo
or hi
at random.)
[!ISSUE] The exact algorithm is not yet decided.
If step
is passed,
returns a random Number
of the form lo + N*step
,
in the range [lo, hi]
(that is, potentially containing lo
or hi
).
Specifically:
- Let
epsilon
be a small value related tostep
, chosen to matchIterator.range
issue #64). - Let
maxN
be the largest integer such thatlo + maxN*step
is less than or equal tohi
. - If
lo + maxN*step
is not withinepsilon
ofhi
, butlo + (maxN+1)*step
is (even if it's greater thanhi
), setmaxN
tomaxN+1
. - Let
N
be a random integer between0
andmaxN
, inclusive. - If
N
ismaxN
, andlo + maxN*step
is withinepsilon
ofhi
, returnhi
. Otherwise, returnlo + N*step
.
Note
This step
behavior is taken directly from CSS's random()
function.
It's also being proposed for Iterator.range()
.
Note
It's probably generally a good thing to match Iterator.range()
in the signatures, which would mean including inclusive
as an options-bag argument, and defaulting int()
and bigint()
(and number()
using a step
) to exclude their hi
value. That would mean, to simulate a d6, you'd need to write either Random.int(1, 7)
or Random.int(1, 6, {inclusive:true})
. I'm unsure if the consistency is worth it, tho...
Returns a random integer Number in the range [lo, hi]
(that is, containing lo
and hi
),
with a uniform distribution.
If step
is passed,
returns a random integer Number of the form lo + N*step
in the range [lo, hi]
.
Note
See Issue 16 for discussion on what algorithm to use, and prior art among other languages.
Identical to Random.int()
, except it returns BigInts instead.
Returns a Uint8Array
of length n
,
filled with random bytes with a uniform distribution.
Fills the passed TypedArray
or ArrayBuffer
with random bytes with a uniform distribution.
If start
and/or end
are passed,
only fills between those positions,
identical to TypedArray.prototype.fill()
.
Note
Note that "random bytes" produces a uniform distribution of values for the integer types, like Uint8Array
, Int32Array
, etc.
It does not do the same for the float types like Float64Array
.
Those types do not have any straightforward definition of "uniform" over their range of possible values.
If you need something smarter, you'll need to write it yourself to meet your exact use-cases.
All of the above functions will also be defined on the Random.Seeded
class as methods, with identical signatures and behavior. That is, Random.number(...)
and new SeededRandom(...).number(...)
will both work.
Precise generation algorithms will be defined for the Random.Seeded
methods, to ensure reproducibility. It's recommended that the Random
versions use the same algorithm, but not strictly required; doing so just lets you use an internal Random.Seeded
object and avoid implementing the same function twice.
- Python's
random
module- random float, with any min/max bounds (and any step)
- random ints, with any min/max bounds (and any step)
- random bytes
- random selection (or N selections with replacement) from a list, with optional weights
- random sampling (or N samples, without replacement) from a list, with optional counts
- randomly shuffle an array
- sample various random distributions: binomal, triangular, beta, exponential, gamma, normal, log-normal, von Mises, Pareto, Weibull
- .Net's
Random
class- random ints, with any min/max bounds
- random floats, with any min/max bounds
- random bytes
- randomly shuffle an array
- Haskell's
RandomGen
interface- random u8/u16/u32/u64, either across the full range or between 0 and max
generate two RNGs from the starting RNG(seeded-random use-case)- random from any type with a range (like all the numeric types, enums, etc), or tuples of such
- random bytes
- random floats between 0 and 1
- Ruby's
Random
class- random floats between 0 and max
- random ints between 0 and max
- random bytes
- Common Lisp's
(random n)
function- random ints between 0 and max
- random floats between 0 and max
- Java's
Random
class- random doubles, defaulting to [0,1) but can be given any min/max bounds
- random ints (or longs), with any min/max bounds
- random bools
- random bytes
- sample Gaussian distribution
- JS
genTest
library- random ints (within certain classes)
- random characters
- random "strings" (relatively short but random lengths, random characters)
- random bools
- random selection (N, with replacement) from a list
- custom random generators
- 2024-04: Initial Stage 0 proposal authored.
- 2025-05: Proposal was accepted for Stage 1, somewhat stripped down (TODO: link to notes)