3

I am facing an issue with rounding decimals in JavaScript using toFixed.

const num1 = (100.555).toFixed(2) // "100.56"
const num2 = (10.555).toFixed(2) // "10.55"

Can any one explain why this behavior happens? Why first example round the decimals to 56 while the second one turn it to 55?

Update: If i add 4 decimals then rounding is differnt.

const num3 = (10.5555).toFixed(2) // "10.56"
Saif Adnan
  • 307
  • 3
  • 12
  • 4
    Does this answer your question? [toFixed javascript function giving strange results?](https://stackoverflow.com/questions/12105787/tofixed-javascript-function-giving-strange-results) – Andreas Apr 26 '20 at 18:22
  • Floating point numbers cannot exactly represent all decimal numbers. By picking a `5` at the end of the decimal you can easily find values that are actually slightly less than the value you expect, and so rounding occurs downwards. – Ben Aston Apr 26 '20 at 18:22

3 Answers3

1

This should fix your problem

// its a rounding bug it can be compenstated by representing numbers exactly in decimal notation.

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
        m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

const num1 = 100.555.toFixedDown(2) 
const num2 = (10.555).toFixedDown(2) 

alert(num1+ ' ' + num2);
Karimov
  • 349
  • 4
  • 8
0

It is because of precision problem in floating numbers....You can find libraries for precision calculation for npm like "npm install bigdecimal" Link here: BigDecimal Reference

var x = new bigdecimal.BigDecimal("123456.123456789012345678901234567890");

and you can use it like that it should be fine.....

Hope this somewhat clarifies your problem....peace

Yousaf Raza
  • 703
  • 3
  • 11
0

Even Math.round() runs into precision issues because it only rounds a whole number.

Math.round(0.4445 * 10) / 10;
// Returns 0.4

Math.round(0.4445 * 100) / 100;
// Returns 0.44

Math.round(0.4445 * 1000) / 1000;
// Returns 0.445

Here is a solution that checks 100 decimals and returns the specified precision

function roundPrecise(num, precision) {
    for (let i = 100; i >= precision; i -= 1) {
        const base = 10 ** i;
        num = (Math.round(num * base) / base);
    }

    return num;
}

roundPrecise(0.4445, 2);
// Returns 0.45

Fields Cage
  • 162
  • 2
  • 10