I'm working in TypeScript. Is there an accepted way of rounding a number to n decimal places, or more, if the precision exists in the number?
The number must be represented as a string to avoid precision errors (e.g. 2.3 - 2 = 0.2999999999999998)
For example:
precision = [2, 6];
tx(0.000000, precision) => 0.00
tx(0.123123, precision) => 0.123123
tx(2.00, precision) => 2.00
tx(2, precision) => 2.00
tx(2.01, precision) => 2.01
tx(2.001, precision) => 2.001
tx(2.000000001, precision) => 2.00
tx(2.000001, precision) => 2.000001
I can use this to deal with funky epsilon errors while still allowing users to enter more precise numbers than a fixed DP.
CodePudding user response:
You can try it like this, which is intentionally verbose:
type PrecisionRange = [min: number, max: number]
function tx(num: number, [min, max]: PrecisionRange): number {
const withoutTrailingZeroes = `${num}`.replace(/0 $/, '') || '0.0'
const digitsAfterDecimalSeparator = withoutTrailingZeroes.includes('.')
? withoutTrailingZeroes.split('.')[1].length
: 0
const toFixedDigits = Math.min(max, Math.max(min, digitsAfterDecimalSeparator))
return Number(num.toFixed(toFixedDigits))
}
const precision: PrecisionRange = [2, 6]
console.log(tx(0.000000, precision)) // 0
console.log(tx(0.123123, precision)) // 0.123123
console.log(tx(2.00, precision)) // 2
console.log(tx(2, precision)) // 2
console.log(tx(2.01, precision)) // 2.01
console.log(tx(2.001, precision)) // 2.001
console.log(tx(2.000000001, precision)) // 2
console.log(tx(2.000001, precision)) // 2.000001
However, 0.00 as a number will always be displayed as 0, as trailing zeroes after the decimal separator are not displayed. If you need them for display purposes, simply adapt the method shown above to this:
function tx(num: number, [min, max]: PrecisionRange): string {
const withoutTrailingZeroes = `${num}`.replace(/0 $/, '') || '0.0'
const digitsAfterDecimalSeparator = withoutTrailingZeroes.includes('.')
? withoutTrailingZeroes.split('.')[1].length
: 0
const toFixedDigits = Math.min(max, Math.max(min, digitsAfterDecimalSeparator))
return num.toFixed(toFixedDigits)
}
CodePudding user response:
Use toLocaleString with minimumFractionDigits and maximumFractionDigits parameters
function tx(value, [minimumFractionDigits, maximumFractionDigits]) {
const result = value.toLocaleString('en-US', {
minimumFractionDigits,
maximumFractionDigits
});
console.log( {value, result} );
return result;
}
const precision = [2, 6];
tx(0.000000, precision)
tx(0.123123, precision)
tx(2.00, precision)
tx(2, precision)
tx(2.01, precision)
tx(2.001, precision)
tx(2.000000001, precision)
tx(2.000001, precision)
