Reputation:
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:
I expected the both are: 3
Upvotes: 1
Views: 222
Reputation: 42649
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.
Upvotes: 0
Reputation: 370689
That extra 1 at the end of 2.4999999999999998
results in it being too close to 2.5 for JavaScript to recognize a difference.
const withEight = 2.4999999999999998;
console.log(2.4999999999999998 === 2.5)
So Math.round(2.4999999999999998)
is the same as Math.round(2.5)
.
And, as the specification requires that, when a number is rounded that is exactly between two integers, the higher integer is preferred.
- Return the integral Number closest to n, preferring the Number closer to +∞ in the case of a tie.
So 3 is the result.
Upvotes: 0
Reputation: 780851
Your input values have more digits of precision than JS floats can hold, so the last digit is being rounded to the nearest binary value. This causes the first one to be read as 2.5
, and Math.round()
rounds this to 3.
You can see this by printing the values of result
before rounding.
let result;
result = 2.4999999999999998;
console.log(result, Math.round(result));
result = 2.4999999999999997;
console.log(result, Math.round(result));
Upvotes: 2