On Friday, 12 October 2012 06:16:03 UTC+10, Danny wrote:
> I'd say that'd be an implementation bug in IE/Opera, I use your number and gave it to Opera 11.62, and gave me the answer you got, then
>
> Math.round(4503599627370499) -> 4503599627370500
Which confirms that Opera is consistent with IE and inconsistent with Firefox and Chrome.
> Math.round(4503599627370495) -> 4503599627370495
>
> Math.round(4503599627370494) -> 4503599627370494
Those numbers are less than 2^52, so don't have the issue.
> Math wise, usually x+0.5 should give x+1 as a rounded figure
Not at all. If x is a decimal, then:
2.75 rounds to 3
2.75 + 0.5 = 3.25 which also rounds to 3
If x is an integer, then for simple rounding you are correct. But as Patricia said, a common rounding algorithm is to round to the nearest even number (sometimes called "bankers rounding") to attenuate rounding inaccuracy.
A peculiarity of javascript numbers is that 4503599627370498.5 is rounded to 4503599627370498 when converted to a number, so there is a kind of natural bankers rounding for such numbers.
> so I see nothing wrong with the implementation in FF/chrome, both good engines btw, however I can work with Math.floor(x+0.5) too.
The problem is that it's impossible to comply with the standard within the bounds of ECMAScript numbers. One fix is to do something like:
function specialRound(n) {
var num = String(n);
// If n is an integer, return it
if (/^[0-9]+$/.test(num)) {
return n;
}
// Otherwise, round it
return Math.round(n);
}
which does what the ES5 specification says. It can be useful:
var a = 4503599627370498;
var b = 4503599627370497;
specialRound(a) - specialRound(b); // 1 in all browsers
Math.round(a) - Math.round(b); // 0 in IE, 1 in Firefox