0

I have this Function, it rounds all numbers to 8 decimals.

exports.roundDown = function(number, decimals) {
  try {
    if (!exports.isNumeric(number)) {
      return number;
    }

    decimals = decimals || 8;

    if (!exports.isNumeric(decimals)) {
      return number;
    }

    const ret =  ( Math.floor( number * Math.pow(10, decimals) ) / Math.pow(10, decimals)*1);

    return ret; //(ret < 0.000001) ? 0 : ret;
  } catch(e) {
    return number;
  } 
}

The problem I have is that numbers like 0.00000003 are rounded to 0.00000002, instead to send the real number (0.00000003), other numbers work fine.

Any idea how to fix this?

Til
  • 5,150
  • 13
  • 26
  • 34
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Jack Bashford Apr 08 '19 at 02:40
  • Obviously, 0.00000003 * Math.pow(10, 8) results in a value slightly smaller than 3, so floor rounds it down to 2. That can happen with floating point, especially with relaltively complex calculations like Math.pow(). Perhaps you can add 0.1 before you apply floor()? Then, a value like 2.99 becomes 3.09 which is then "floored" to 3.0. – Rudy Velthuis Apr 08 '19 at 14:40

2 Answers2

2

Have you tried the toFixed?

var num = 0.00000002473;
var n = num.toFixed(8);
//n contains 0.00000002
James Arnold
  • 698
  • 3
  • 9
  • 22
1

The reason is, that 0.00000003 does not exists. So you can't never round a number to this value. On scanning, it is binary rounded to the nearest possible number. toPrecision(18) shows the number more exact:

(0.00000003).toPrecision(18) // "2.99999999999999973e-8"

And that is why toFixed()returns a string and not a number. In other words: It is impossible to round number to exact 8 decimal digits, except it is binary based number like 0.5, 0.125

Wiimm
  • 2,971
  • 1
  • 15
  • 25