exactnumber
Version:
Arbitrary-precision decimals. Enables making math calculations with rational numbers, without precision loss.
63 lines (51 loc) • 1.98 kB
text/typescript
/* eslint-disable @typescript-eslint/naming-convention */
/** Trims trailing zeros from numbers in fixed-point format (1.23000 -> 1.23) */
export const trimTrailingZerosFromFixed = (num: string): string => {
const pointPos = num.indexOf('.');
if (pointPos === -1) return num;
let firstZeroAt = num.length;
while (firstZeroAt > pointPos && num.charAt(firstZeroAt - 1) === '0') firstZeroAt--;
const newLength = pointPos === firstZeroAt - 1 ? pointPos : firstZeroAt;
if (newLength === 0) return '0';
return num.slice(0, newLength);
};
export const bigIntToStr = (num: bigint, inputDecimals: number, outputDecimals: number, trimZeros: boolean): string => {
let str = num.toString();
if (inputDecimals === 0 && outputDecimals === 0) return str;
const isNegative = str.startsWith('-');
if (isNegative) {
str = str.slice(1);
}
if (inputDecimals >= str.length) {
str = '0'.repeat(inputDecimals - str.length + 1) + str;
}
if (inputDecimals > 0) {
const wholePart = str.slice(0, -inputDecimals);
const fracPart = str.slice(-inputDecimals);
const outFracPart =
outputDecimals <= inputDecimals
? fracPart.slice(0, outputDecimals)
: `${fracPart}${'0'.repeat(outputDecimals - inputDecimals)}`;
if (outFracPart.length !== 0) {
str = `${wholePart}.${outFracPart}`;
if (trimZeros) {
str = trimTrailingZerosFromFixed(str);
}
} else {
str = wholePart;
}
} else if (outputDecimals > 0 && !trimZeros) {
str = `${str}.${'0'.repeat(outputDecimals)}`;
}
return isNegative ? `-${str}` : str;
};
// BigInt literals (1n) are not supported by all parsers
// also, the BigInt() constructor is still too slow to call in a loop
export const _0N = BigInt(0);
export const _1N = BigInt(1);
export const _2N = BigInt(2);
export const _3N = BigInt(3);
export const _4N = BigInt(4);
export const _5N = BigInt(5);
export const _10N = BigInt(10);
export const _24N = BigInt(24);