import { getRandomUnitValue } from "./base.ts" // 默认下界为 0。 // 当调用方未传入任何参数,randomNumber 会从 0 开始生成随机数。 const internalDefaultRandomNumberMin = 0 // 默认上界为 1。 // 这使 randomNumber() 的行为与常见的随机小数语义保持一致。 const internalDefaultRandomNumberMax = 1 // Step 1: 校验范围端点。 // // randomNumber 只接受有限数值,避免把 Infinity 或 NaN 带入后续区间计算。 const internalAssertRandomNumberBound = (value: number, name: string): void => { if (Number.isFinite(value) === false) { throw new TypeError(`Expected ${name} to be a finite number, got: ${value}`) } } // Step 2: 规范化随机区间。 // // 支持三种调用方式: // - randomNumber() -> [0, 1) // - randomNumber(max) -> [0, max) 或 [max, 0) // - randomNumber(a, b) -> [min(a, b), max(a, b)) const internalNormalizeRandomNumberRange = ( a?: number | undefined, b?: number | undefined, ): [number, number] => { if (a === undefined && b === undefined) { return [internalDefaultRandomNumberMin, internalDefaultRandomNumberMax] } if (a !== undefined && b === undefined) { internalAssertRandomNumberBound(a, "max") return a >= 0 ? [0, a] : [a, 0] } if (a === undefined || b === undefined) { throw new TypeError("Expected both range bounds when specifying two arguments") } internalAssertRandomNumberBound(a, "a") internalAssertRandomNumberBound(b, "b") return a <= b ? [a, b] : [b, a] } /** * @description 生成指定区间内的随机数。 * * 当未传入参数时,返回 `0` 到 `1` 之间的随机小数;当传入一个参数时,将其视为区间另一端点;当传入两个参数时,会按较小值到较大值规范化区间。 * 结果包含下界,不包含上界;若上下界相同,则直接返回该值。 * * @example * ``` * const sample1 = randomNumber() * // Expect: true * const example1 = sample1 >= 0 && sample1 < 1 * const sample2 = randomNumber(10, 3) * // Expect: true * const example2 = sample2 >= 3 && sample2 < 10 * // Expect: 4 * const example3 = randomNumber(4, 4) * ``` */ export const randomNumber = (a?: number | undefined, b?: number | undefined): number => { const [min, max] = internalNormalizeRandomNumberRange(a, b) if (min === max) { return min } return getRandomUnitValue() * (max - min) + min }