Files
test/packages/util/src/numbers.ts
Benjamin Falch 2bc741fb78
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled
adding monkeytype
2026-04-23 13:53:44 +02:00

159 lines
4.2 KiB
TypeScript

//pin implementations
const random = Math.random;
const ceil = Math.ceil;
const floor = Math.floor;
/**
* Rounds a number to one decimal places.
* @param num The number to round.
* @returns The input number rounded to one decimal places.
*/
export function roundTo1(num: number): number {
return Math.round((num + Number.EPSILON) * 10) / 10;
}
/**
* Rounds a number to two decimal places.
* @param num The number to round.
* @returns The input number rounded to two decimal places.
*/
export function roundTo2(num: number): number {
return Math.round((num + Number.EPSILON) * 100) / 100;
}
/**
* Calculates the mean (average) of an array of numbers.
* @param array An array of numbers.
* @returns The mean of the input array.
*/
export function mean(array: number[]): number {
try {
return (
array.reduce((previous, current) => (current += previous)) / array.length
);
} catch (e) {
return 0;
}
}
/**
* Calculates the standard deviation of an array of numbers.
* @param array An array of numbers.
* @returns The standard deviation of the input array.
*/
export function stdDev(array: number[]): number {
try {
const n = array.length;
const meanValue = mean(array);
return Math.sqrt(
array.map((x) => Math.pow(x - meanValue, 2)).reduce((a, b) => a + b) / n,
);
} catch (e) {
return 0;
}
}
/**
* Calculates the median of an array of numbers.
* https://www.w3resource.com/javascript-exercises/fundamental/javascript-fundamental-exercise-88.php
* @param arr An array of numbers.
* @returns The median of the input array.
*/
export function median(arr: number[]): number {
try {
const mid = Math.floor(arr.length / 2),
nums = [...arr].sort((a, b) => a - b);
return arr.length % 2 !== 0
? (nums[mid] as number)
: ((nums[mid - 1] as number) + (nums[mid] as number)) / 2;
} catch (e) {
return 0;
}
}
/**
* Calculates consistency by mapping COV from [0, +infinity) to [100, 0).
* The mapping function is a version of the sigmoid function tanh(x) that is closer to the identity function tanh(arctanh(x)) in [0, 1).
* @param cov The coefficient of variation of an array of numbers (standard deviation / mean).
* @returns Consistency
*/
export function kogasa(cov: number): number {
return (
100 * (1 - Math.tanh(cov + Math.pow(cov, 3) / 3 + Math.pow(cov, 5) / 5))
);
}
/**
* Gets an integer between min and max, both are inclusive.
* @param min
* @param max
* @returns Random integer betwen min and max.
*/
export function randomIntFromRange(min: number, max: number): number {
const minNorm = ceil(min);
const maxNorm = floor(max);
return floor(random() * (maxNorm - minNorm + 1) + minNorm);
}
/**
* Maps a value from one range to another.
* @param value The value to map.
* @param inMin Input range minimum.
* @param inMax Input range maximum.
* @param outMin Output range minimum.
* @param outMax Output range maximum.
* @param clamp If true, the result is clamped to the output range. Default true.
* @returns The mapped value.
*/
export function mapRange(
value: number,
inMin: number,
inMax: number,
outMin: number,
outMax: number,
clamp = true,
): number {
if (inMin === inMax) {
return outMin;
}
const result =
((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
if (clamp) {
if (outMin < outMax) {
return Math.min(Math.max(result, outMin), outMax);
} else {
return Math.max(Math.min(result, outMin), outMax);
}
}
return result;
}
/**
* Checks if a value is a safe number. Safe numbers are finite and not NaN.
* @param value The value to check.
* @returns True if the value is a safe number, false otherwise.
*/
export function isSafeNumber(value: unknown): value is number {
if (typeof value === "number") {
return !isNaN(value) && isFinite(value);
}
return false;
}
/**
* Converts a number to a safe number or undefined. NaN, Infinity, and -Infinity are converted to undefined.
* @param value The value to convert.
* @returns The input number if it is safe, undefined otherwise.
*/
export function safeNumber(
value: number | undefined | null,
): number | undefined {
if (isSafeNumber(value)) {
return value;
}
return undefined;
}