Skip to content

Instantly share code, notes, and snippets.

@bjesuiter
Last active September 9, 2024 12:37
Show Gist options
  • Save bjesuiter/cacc24e1ecfdca27f36acfc8271dd976 to your computer and use it in GitHub Desktop.
Save bjesuiter/cacc24e1ecfdca27f36acfc8271dd976 to your computer and use it in GitHub Desktop.
JS/TS Tricks
/**
* Basic Problem: JS Floating Point Math is highly inaccurate.
* Found this thread: https://stackoverflow.com/questions/11832914/how-to-round-to-at-most-2-decimal-places-if-necessary
*
* Best solution: Use a library with correct implementation of floating point math.
*
* - mathjs (CAUTION: not math.js!): https://www.npmjs.com/package/mathjs
* - is basically complete, but is FAT: 732 kB, 188 kB minified
* - see https://bundlephobia.com/package/[email protected]
*
* - decimal.js: https://www.npmjs.com/package/decimal.js
* - still 31.1 kB, 12.3kB minified
* - good: last Publish in 2022 (today: 2024-09-09)
*
* - currency.js: https://www.npmjs.com/package/currency.js
* - 2.2kB, 1kB minified
* - no dependencies
* - BUT: only compatible with TS allowSyntheticDefaultImports: true + default import
*
* Second best solution: Use a custom implementation of roundToPrecision
* tt-bj2 selected (on 2024-09-09):
* https://stackoverflow.com/questions/11832914/how-to-round-to-at-most-2-decimal-places-if-necessary#:~:text=Solution%202%3A%20purely%20mathematical%20(Number.EPSILON)
*
*/
// Decimal round (half away from zero)
export function roundToPrecision(value: number, precision: number): number {
const p = Math.pow(10, precision || 0);
const n = value * p * (1 + Number.EPSILON);
return Math.round(n) / p;
}
// Decimal ceil
export function ceilToPrecision(value: number, precision: number): number {
const p = Math.pow(10, precision || 0);
const n = value * p * (1 - Math.sign(value) * Number.EPSILON);
return Math.ceil(n) / p;
}
// Decimal floor
export function floorToPrecision(value: number, precision: number): number {
const p = Math.pow(10, precision || 0);
const n = value * p * (1 + Math.sign(value) * Number.EPSILON);
return Math.floor(n) / p;
}
// Decimal trunc
export function truncToPrecision(value: number, precision: number): number {
return (value < 0 ? ceilToPrecision : floorToPrecision)(value, precision);
}
// Format using fixed-point notation
export function toFixed(value: number, precision: number): string {
return roundToPrecision(value, precision).toFixed(precision);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment