Show HN: Aimless.js – the missing js randomness library
github.com
github.com
const randIntRange = (i, j, engine = defaultEngine) => {
const min = Math.ceil(i)
const max = Math.floor(j)
return Math.floor(engine() * (max - min + 1)) + min
}
If you assume engine() outputs, say, 64 bits of entropy, any number range that is not an even factor of 2^64 will exhibit intermittent bias where the numbers are rounded.The only correct way to do this is to do rejection sampling: generate an integer x with log2(max - min) bits and if x >= max - min retry until you do:
function randBelow(n) {
const nbits = Math.ceil(Math.log2(n));
while (true) {
const x = getRandBits(nbits);
if (x < n) { return x; }
}
}
function randIntHalfOpenRange(min, max) {
return min + randBelow(max - min);
}
function randIntRange(min, max) {
return randIntHalfOpenRange(min, max + 1);
}
The primitive you want for building distributions on is not to generate a floating point number between 0.0 and 1.0, but to generate an integer of at most x bits.Maybe there is good reason for this. I'm not real familiar with this space. It's not so hard to implement something yourself. But I suspect the description of "missing js randomness library" may have some merit.
https://fakerjs.dev/api/helpers.html#arrayelement
I believe is what you're looking for. The issue, as I recall, is that all of Faker is random, so what does it mean to have a `random` module namespace. We moved it out of a hope for improved clarity.
It's nice to see aimless.js support it.
Crazy to me that `Math.random` doesn't accept a seed as an optional param.
Another case are unit tests with random-generated cases. At a minimum you want to know the seed of the last run and have that reported. On CI system you would want it to be deterministic.
Where you want there not to be a seed is in crypto, or possibly a game like poker or even tetris.
I had to make one myself and I never thought it'd be something I'd ever need to do
This library seems to solve that problem and half a dozen others! Like: Reading code with functions named for their purpose is better than a string of arithmetic operations in most cases. Thank you for sharing this! Will use in my game! [2]
const weightedDiceRoll =
weighted(
[1,2,3,4,5,6],
[1,1,1,1,1,10]
)
// will return 6 much more often than the other options
0: https://news.ycombinator.com/item?id=34742505Looking at random-js, the barrier to entry is higher. I've looked at randomness libraries and that's the feeling they gave me: That I would need to learn how randomness works, rather than just calling a function for what I want; a random int, a weighted random. Cmd+F "weighted" doesn't find anything on both of those projects' readmes.
There's a tradeoff for simplicity, but in many cases I'll take it. This is the iPhone of randomness and that's what I needed to feel comfortable using it rather than rolling my own.
const randomPermutation = arr => intSequence(0, arr.length - 1).map(i => arr[i])
console.log(randomPermutation(['a', 'b', 'c'])const randomSeq = sequence([1,2,3]) // could return [3,1,2], [2,3,1], etc.
Thumbs up. Carry on.