@augment-vir/common
Version:
A collection of augments, helpers types, functions, and classes for any JavaScript environment.
35 lines (34 loc) • 1.39 kB
JavaScript
import { ensureMinMax } from '@augment-vir/core';
/**
* Creates a random integer (no decimal points are included) between the given min and max values
* (inclusive).
*
* This function uses cryptographically secure randomness.
*
* @category Random
* @category Package : @augment-vir/common
* @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common)
*/
export function randomInteger({ min: rawMin, max: rawMax }) {
const { min, max } = ensureMinMax({ min: Math.floor(rawMin), max: Math.floor(rawMax) });
const range = max - min + 1;
const bitsNeeded = Math.ceil(Math.log2(range));
const neededBytes = Math.ceil(bitsNeeded / 8);
/**
* Testing on my system maxes out at 65,536 (Node) or 65,537 (Safari / Chrome / Firefox) bytes.
* I don't know why, and that may be system dependent, I don't know.
*/
if (neededBytes > 65_000) {
throw new RangeError(`Cannot create a random integer so large. ({min: ${min}, max: ${max}})`);
}
const cutoff = Math.floor(256 ** neededBytes / range) * range;
const currentBytes = new Uint8Array(neededBytes);
let value;
do {
crypto.getRandomValues(currentBytes);
value = currentBytes.reduce((accum, byte, index) => {
return accum + byte * 256 ** index;
}, 0);
} while (value >= cutoff);
return min + (value % range);
}