80 lines
1.9 KiB
TypeScript
80 lines
1.9 KiB
TypeScript
/**
|
||
* 纯数学工具(无随机、无平台依赖),供 generators / 模板引擎使用
|
||
*/
|
||
|
||
/** 将数值限制在 [min, max] */
|
||
export function clamp(value: number, min: number, max: number): number {
|
||
return Math.min(max, Math.max(min, value));
|
||
}
|
||
|
||
/** 最大公约数(非负整数) */
|
||
export function gcd(a: number, b: number): number {
|
||
let x = Math.abs(Math.trunc(a));
|
||
let y = Math.abs(Math.trunc(b));
|
||
while (y !== 0) {
|
||
const t = y;
|
||
y = x % y;
|
||
x = t;
|
||
}
|
||
return x || 1;
|
||
}
|
||
|
||
/** 最小公倍数 */
|
||
export function lcm(a: number, b: number): number {
|
||
const g = gcd(a, b);
|
||
return Math.abs(Math.trunc(a) * Math.trunc(b)) / g;
|
||
}
|
||
|
||
/** 闭区间 [min, max] 上的整数列表 */
|
||
export function integerRangeInclusive(min: number, max: number): number[] {
|
||
const lo = Math.min(min, max);
|
||
const hi = Math.max(min, max);
|
||
const out: number[] = [];
|
||
for (let i = lo; i <= hi; i += 1) {
|
||
out.push(i);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
/** 数组求和 */
|
||
export function sum(numbers: readonly number[]): number {
|
||
let s = 0;
|
||
for (let i = 0; i < numbers.length; i += 1) {
|
||
s += numbers[i];
|
||
}
|
||
return s;
|
||
}
|
||
|
||
/** 算术平均(空数组为 0) */
|
||
export function mean(numbers: readonly number[]): number {
|
||
if (numbers.length === 0) return 0;
|
||
return sum(numbers) / numbers.length;
|
||
}
|
||
|
||
/** 各位数字之和(十进制,忽略负号) */
|
||
export function digitSum(n: number): number {
|
||
let v = Math.abs(Math.trunc(n));
|
||
let s = 0;
|
||
while (v > 0) {
|
||
s += v % 10;
|
||
v = Math.floor(v / 10);
|
||
}
|
||
return s;
|
||
}
|
||
|
||
export function isEven(n: number): boolean {
|
||
return n % 2 === 0;
|
||
}
|
||
|
||
export function isOdd(n: number): boolean {
|
||
return !isEven(n);
|
||
}
|
||
|
||
/**
|
||
* 将浮点数舍入到指定小数位(避免 0.1+0.2 展示问题)
|
||
*/
|
||
export function roundToDecimals(value: number, decimals: number): number {
|
||
const p = 10 ** decimals;
|
||
return Math.round(value * p) / p;
|
||
}
|