-
-
Notifications
You must be signed in to change notification settings - Fork 30
Open
Description
uniform-int currently functions by stretching the output range of the RNG into the desired range. However, this is not strictly correct as it depends on the output size of the RNG. For instance, with a small-scale example, if the RNG only outputs 16 bits and we're generating a number from 0 to 5:
>>> collections.Counter(i * 6 // 0xffff for i in range(0xffff))
Counter({0: 10923, 2: 10923, 4: 10923, 1: 10922, 3: 10922, 5: 10922})
We can run a simulation to see the effect of this as well:
const random = require("random")
const hist = new Map();
for (let i = 0; i < 20000000; i++) {
const n = random.int(0, 5);
hist.set(n, (hist.get(n) || 0) + 1);
}
and we get:
Map(6) {
4 => 3334526,
5 => 3333539,
3 => 3334684,
1 => 3331604,
0 => 3333306,
2 => 3332341
}
In order to get a truly uniform distribution, the generator needs to instead:
- operate by generating bits with a uniform distribution (it's likely that Math.random will at least be uniform over 64 bits, so it's possible to generate 64 bits at a time).
- generate enough bits to hold the max value
- if the generated number is > max value, discard and try again
https://github.com/python/cpython/blob/8a0d9a6bb77a72cd8b9ece01b7c1163fff28029a/Lib/random.py#L235-L243 has an example of how it works.
Metadata
Metadata
Assignees
Labels
No labels