Last active
May 9, 2022 15:10
-
-
Save jabney/003ba1504c13735aad6da18f618c8691 to your computer and use it in GitHub Desktop.
Seedable random numbers using a hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
const crypto = require("crypto"); | |
/** | |
* @param {string|number} [seed] | |
* @param {number} [offset] | |
*/ | |
const createRng = (seed = 0, offset = 0) => { | |
const numBytes = 6; // 48 bits | |
const maxInt = 2 ** 48; | |
let count = offset; | |
/** | |
* @param {number|string} seed | |
*/ | |
const createHash = (seed) => { | |
const hash = crypto.createHash("sha256"); | |
hash.update(seed.toString()); | |
return hash; | |
}; | |
/** | |
* @param {crypto.Hash} hash | |
*/ | |
const getInt = (hash) => { | |
const bytes = hash.digest("hex").slice(-2 * numBytes); | |
return parseInt(bytes, 16); | |
}; | |
const randomFloat = () => { | |
count = (count % Number.MAX_SAFE_INTEGER) + 1; | |
const hash = createHash(seed); | |
hash.update(count.toString()); | |
return getInt(hash) / maxInt; | |
}; | |
/** | |
* @param {number} min inclusive | |
* @param {number} max exclusive | |
*/ | |
const randomInt = (min = 0, max = maxInt) => { | |
const f = randomFloat(); | |
return Math.floor(min + f * (max - min)); | |
}; | |
return Object.freeze({ | |
maxInt, | |
/** | |
* Produce a random int | |
*/ | |
randomInt, | |
/** | |
* Produce a random float | |
*/ | |
randomFloat, | |
/** | |
* Produce a random float | |
*/ | |
get value() { | |
return randomFloat(); | |
}, | |
}); | |
}; | |
const rng = createRng(0); | |
const iters = 1e5; | |
let hist = {}; | |
for (let i = 0; i < iters; i++) { | |
const n = rng.randomInt(0, 10); | |
hist[n] = (hist[n] || 0) + 1; | |
} | |
console.log(hist); | |
hist = {}; | |
for (let i = 0; i < iters; i++) { | |
const n = crypto.randomInt(0, 10); | |
hist[n] = (hist[n] || 0) + 1; | |
} | |
console.log(hist); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment