Search code examples
javascriptmath.round

I hava a very simple question about Math.round() in javascript


code:

let result;

result = 2.4999999999999998;
console.log(Math.round(result));

result = 2.4999999999999997;
console.log(Math.round(result));

The rounding point isn't 5 ? (Although I know that numbers in JavaScript always occupy 64 bits of memory. Numbers up to 15 integer digits and 17 decimal digits can be defined and displayed in JavaScript.) why the result in console is:

result in console

I expected the both are: 3


Solution

  • The surprising behavior is not really related to Math.round(). The rounding happens already at the point of parsing the numeric literal, and you can see it by echoing the numbers directly without any explicit rounding:

    > 2.4999999999999998
    2.5
    > 2.4999999999999997
    2.4999999999999996 
    

    So the first number is immediately rounded up and the second down - but not corresponding to the common rules of decimal rounding (e.g. the second number still have the same number of digits).

    The reason is that the numeric literal is converted to a 64-bit floating point number. This has a precision of 53 binary digits. The input number is therefore rounded to the closest number which can be represented with 53 binary digits.

    The binary representation of 2.4999999999999996 is:

    10.011111111111111111111111111111111111111111111111111
    

    This is 53 significant binary digits, and the next higher binary number is therefore:

    10.100000000000000000000000000000000000000000000000000
    

    Which is 2.5 in decimal.

    So numbers between 2.4999999999999996 and 2.5 cannot be represented exactly and have to be rounded up or down to fit in the floating-point format. So 2.4999999999999997 is rounded down to 2.4999999999999996 and 2.4999999999999998 is rounded up to 2.5.

    (There is a special rule because 2.4999999999999998 is halfway between the two valid values. In this case the value is rounded towards the even significand.)

    Math.round() on the other hand follows decimal rounding rules, which means we round up on 0.5 and higher. The result of the Math.round() operation is then straightforward: 2.5 is rounded up to 3 and 2.4999999999999996 is rounded down to 2.