Home > Enterprise >  Round a number to 2 or more decimal places
Round a number to 2 or more decimal places

Time:08-17

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)

  • Related