export function isNumber(val: unknown) { return !isNaN(parseInt(String(val))); } export class DecimalPrecision { // Decimal round (half away from zero) static round(num: number, decimalPlaces: number) { const p = Math.pow(10, decimalPlaces || 0); const n = num * p * (1 + Number.EPSILON); return Math.round(n) / p; } // Decimal ceil static ceil(num: number, decimalPlaces: number) { const p = Math.pow(10, decimalPlaces || 0); const n = num * p * (1 - Math.sign(num) * Number.EPSILON); return Math.ceil(n) / p; } // Decimal floor static floor(num: number, decimalPlaces: number) { const p = Math.pow(10, decimalPlaces || 0); const n = num * p * (1 + Math.sign(num) * Number.EPSILON); return Math.floor(n) / p; } // Decimal trunc static trunc(num: number, decimalPlaces: number) { return (num < 0 ? DecimalPrecision.ceil : DecimalPrecision.floor)( num, decimalPlaces ); } // Format using fixed-point notation static toFixed(num: number, decimalPlaces: number) { return DecimalPrecision.round(num, decimalPlaces).toFixed(decimalPlaces); } // Count decimals static countDecimals(num: number) { const s = num.toExponential(); const [before, after] = s.split("e"); const exp = parseInt(after); const dec = before.split(".")[1]; const count = (dec || "").length - exp; return Math.max(0, count); } }