import { getRandomUnitValue } from "./base.ts" // 默认整数下界为 0。 // 当 randomInteger 只传入一个端点时,会与 0 共同构成整数区间。 const internalDefaultRandomIntegerValue = 0 // Step 1: 校验整数范围端点。 // // randomInteger 只接受安全整数,避免把小数或超出安全范围的值带入整数区间计算。 const internalAssertRandomIntegerBound = (value: number, name: string): void => { if (Number.isSafeInteger(value) === false) { throw new TypeError(`Expected ${name} to be a safe integer, got: ${value}`) } } // Step 2: 规范化随机整数区间。 // // 支持两种调用方式: // - randomInteger(max) -> [0, max] 或 [max, 0] // - randomInteger(a, b) -> [min(a, b), max(a, b)] const internalNormalizeRandomIntegerRange = ( a: number, b?: number | undefined, ): [number, number] => { internalAssertRandomIntegerBound(a, b === undefined ? "max" : "a") if (b === undefined) { return a >= internalDefaultRandomIntegerValue ? [internalDefaultRandomIntegerValue, a] : [a, internalDefaultRandomIntegerValue] } internalAssertRandomIntegerBound(b, "b") return a <= b ? [a, b] : [b, a] } /** * @description 生成指定区间内的随机整数。 * * 当传入一个参数时,将其视为区间另一端点,并与 `0` 共同构成整数区间;当传入两个参数时,会按较小值到较大值规范化区间。 * 结果同时包含下界与上界;若上下界相同,则直接返回该值。 * * @example * ``` * const sample1 = randomInteger(5) * // Expect: true * const example1 = sample1 >= 0 && sample1 <= 5 * const sample2 = randomInteger(8, 3) * // Expect: true * const example2 = sample2 >= 3 && sample2 <= 8 * // Expect: 4 * const example3 = randomInteger(4, 4) * ``` */ export const randomInteger = (a: number, b?: number | undefined): number => { const [min, max] = internalNormalizeRandomIntegerRange(a, b) if (min === max) { return min } return Math.floor(getRandomUnitValue() * (max - min + 1)) + min }