Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #16549 > unrolled thread

Specification error for Math.round

Started byRobG <rgqld@iinet.net.au>
First post2012-10-10 19:52 -0700
Last post2012-10-12 22:48 +0100
Articles 13 — 7 participants

Back to article view | Back to comp.lang.javascript


Contents

  Specification error for Math.round RobG <rgqld@iinet.net.au> - 2012-10-10 19:52 -0700
    Re: Specification error for Math.round Patricia Shanahan <pats@acm.org> - 2012-10-11 07:29 +0100
      Re: Specification error for Math.round Dr J R Stockton <reply1241@merlyn.demon.co.uk.invalid> - 2012-10-12 23:00 +0100
    Re: Specification error for Math.round Danny <dann90038@gmail.com> - 2012-10-11 13:16 -0700
      Re: Specification error for Math.round Patricia Shanahan <pats@acm.org> - 2012-10-12 00:14 +0100
      Re: Specification error for Math.round RobG <rgqld@iinet.net.au> - 2012-10-11 21:46 -0700
        Re: Specification error for Math.round Patricia Shanahan <pats@acm.org> - 2012-10-12 08:28 +0100
          Re: Specification error for Math.round Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-10-13 22:14 +0200
            Re: Specification error for Math.round Patricia Shanahan <pats@acm.org> - 2012-10-13 21:45 +0100
              Re: Specification error for Math.round "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2012-10-13 23:59 +0200
          Re: Specification error for Math.round Dr J R Stockton <reply1241@merlyn.demon.co.uk.invalid> - 2012-10-13 19:31 +0100
        Re: Specification error for Math.round Denis McMahon <denismfmcmahon@gmail.com> - 2012-10-14 11:09 +0000
    Re: Specification error for Math.round Dr J R Stockton <reply1241@merlyn.demon.co.uk.invalid> - 2012-10-12 22:48 +0100

#16549 — Specification error for Math.round

FromRobG <rgqld@iinet.net.au>
Date2012-10-10 19:52 -0700
SubjectSpecification error for Math.round
Message-ID<6dc8cb55-c29c-4bb2-ab6d-d9a9447cffd4@googlegroups.com>
The largest contiguous integer (i.e. the largest of the continuous sequence that can be represented exactly) in Javascript is 2^53, so it might be expected that integers below this value should not exhibit precision errors.

The ES5 specification for Math.round(x)[1] says that:

  "If x is already an integer, the result is x"

and that:

  "The value of Math.round(x) is the same as the
   value of Math.floor(x+0.5)"

So one might expect Math.round(x) to simply return x for all integers up to 2^53. But if the Math.floor criterion is applied, the limit is 2^52 (4503599627370496), so these criteria conflict for odd numbers between 2^52 and 2^53.

Browsers must choose which criterion they will respect, naturally some of the more popular ones have chosen differently.

e.g. in Firefox and Chrome:

    Math.round(4503599627370496)       -> 4503599627370496
    Math.round(4503599627370497)       -> 4503599627370497
    Math.floor(4503599627370497 + 0.5) -> 4503599627370498

which satisfies the first criterion, but fails the second.

In IE and Opera:

    Math.round(4503599627370496)       -> 4503599627370496
    Math.round(4503599627370497)       -> 4503599627370498
    Math.floor(4503599627370497 + 0.5) -> 4503599627370498

which satisfies the second criterion but not the first.

There are arguments to support both cases but there is no conclusive agrument one way or the other. It seems to me that this can't be called a bug in implementations, but is a specification error for providing incompatible requirements.

Is it possible to meet both criteria within the bounds of javascript numbers? 

Is there some overwhelmingly good argument to support one criterion and not the other?


1. http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.15
2. http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.6

-- 
Rob

[toc] | [next] | [standalone]


#16550

FromPatricia Shanahan <pats@acm.org>
Date2012-10-11 07:29 +0100
Message-ID<sMudna--d5iv-uvNnZ2dnUVZ_tydnZ2d@earthlink.com>
In reply to#16549
RobG wrote:
...
> The ES5 specification for Math.round(x)[1] says that:
> 
>   "If x is already an integer, the result is x"
> 
> and that:
> 
>   "The value of Math.round(x) is the same as the
>    value of Math.floor(x+0.5)"
...

The second rule introduces another oddity.

Most rounding is being done according to IEEE 754 round to nearest, in
which ties go to the even number. This particular rounding is sending
ties to the larger number. For example, Firefox gives "9" as the result
of "Math.round(8.5)".

That means that the inconsistency cannot be fixed by just saying that
the rounding is being done according to the normal round to nearest
rules, the way the corresponding function in java.lang.Math, rint(), is
specified. The second specification, or something equivalent to it, has
to be kept at least for non-integer inputs.

Patricia

[toc] | [prev] | [next] | [standalone]


#16594

FromDr J R Stockton <reply1241@merlyn.demon.co.uk.invalid>
Date2012-10-12 23:00 +0100
Message-ID<Jml6BCIJMJeQFwYf@invalid.uk.co.demon.merlyn.invalid>
In reply to#16550
In comp.lang.javascript message <sMudna--d5iv-uvNnZ2dnUVZ_tydnZ2d@earthl
ink.com>, Thu, 11 Oct 2012 07:29:07, Patricia Shanahan <pats@acm.org>
posted:

>Most rounding is being done according to IEEE 754 round to nearest, in
>which ties go to the even number. This particular rounding is sending
>ties to the larger number. For example, Firefox gives "9" as the result
>of "Math.round(8.5)".

Bankers' Rounding is good, I suppose, for Bankers.  It is bad for
technical work.  The ECMA spec should keep Math.round as it is, and add
Math.roundBankers.

<http://www.merlyn.demon.co.uk/js-rndg3.htm#CT> purports to provide
Bankers' Rounding, of two types.

Since JavaScript non-integer arithmetic is commonly inexact, it may be
desirable to round values which are almost half-integer to half-integer
before doing Bankers; my page provides that.

To get the ECMA standard debugged,
"omnes labores adhuc exantlati (exatlanti?) omni fructu caruissent"
(Enestrom 304).

-- 
 (c) John Stockton, nr London UK. E-addr via Homepage. Turnpike v6.05  MIME.
   <http://www.merlyn.demon.co.uk/>  TP/BP/Delphi/&c., FAQqy topics & links;
   <http://www.merlyn.demon.co.uk/clpb-faq.txt>    RAH Prins : c.l.p.b mFAQ;
   <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>  Timo Salmi's Turbo Pascal FAQ.

[toc] | [prev] | [next] | [standalone]


#16563

FromDanny <dann90038@gmail.com>
Date2012-10-11 13:16 -0700
Message-ID<b07ab1c9-fbf6-4c55-964e-17a69be1a7f3@googlegroups.com>
In reply to#16549
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
Math.round(4503599627370495) -> 4503599627370495
Math.round(4503599627370494) -> 4503599627370494

Math wise, usually x+0.5 should give x+1 as a rounded figure :), 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.

Web standards are practical guidelines to go by, but in the end, the vendors will implement as best they can within those guidelines.  Bearing in mind that all major browser vendors have membership in the ES board.

[toc] | [prev] | [next] | [standalone]


#16568

FromPatricia Shanahan <pats@acm.org>
Date2012-10-12 00:14 +0100
Message-ID<E6OdncHspu9Dz-rNnZ2dnUVZ_qCdnZ2d@earthlink.com>
In reply to#16563
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
> Math.round(4503599627370495) -> 4503599627370495
> Math.round(4503599627370494) -> 4503599627370494
> 
> Math wise, usually x+0.5 should give x+1 as a rounded figure :), 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.
> 
> Web standards are practical guidelines to go by, but in the end, the vendors will implement as best they can within those guidelines.  Bearing in mind that all major browser vendors have membership in the ES board.

I think a standard should be designed so that it is at least possible to
implement, even if some implementations deviate from it. This particular
one is not.

Patricia

[toc] | [prev] | [next] | [standalone]


#16570

FromRobG <rgqld@iinet.net.au>
Date2012-10-11 21:46 -0700
Message-ID<39e06fb5-7d74-4b5d-83bf-d2f7b3181168@googlegroups.com>
In reply to#16563
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

[toc] | [prev] | [next] | [standalone]


#16573

FromPatricia Shanahan <pats@acm.org>
Date2012-10-12 08:28 +0100
Message-ID<CbGdnbfKl-UJW-rNnZ2dnUVZ_vydnZ2d@earthlink.com>
In reply to#16570
RobG wrote:
...
> 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.
...

It's perhaps worth emphasizing the fact that the ties go to nearest even
style of rounding is the normal rounding mode in JavaScript arithmetic.
It is what you get if you add two numbers, and the exact sum has more
than 53 bits, ignoring leading and trailing zeros.

Patricia

[toc] | [prev] | [next] | [standalone]


#16607

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-10-13 22:14 +0200
Message-ID<1836672.QNfzn4bpLz@PointedEars.de>
In reply to#16573
Patricia Shanahan wrote:

> RobG wrote:
>> 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.
> 
> It's perhaps worth emphasizing the fact that the ties go to nearest even
> style of rounding is the normal rounding mode in JavaScript arithmetic.
                                                   ^^^^^^^^^^
That would be _ECMAScript_.¹  But you are oversimplifying, see ES 5.1 
§9.8.1.  One additional caveat here is that the numbers you *see* are only 
string representations of Number values.

BTW, your quoting style is suboptimal.  Omissions, if any, should be 
indicated at the same quotation level as the text from which text has been 
omitted.  `[...]' or (typographically correct) `[…]' should be used to 
indicate omission, to distinguish it from an ellipsis in the quoted text.


PointedEars
___________
¹  But perhaps one should be grateful already that you are not writing
   "Javascript" or "javascript" instead.  Sigh. [psf 10.1]
-- 
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

[toc] | [prev] | [next] | [standalone]


#16608

FromPatricia Shanahan <pats@acm.org>
Date2012-10-13 21:45 +0100
Message-ID<TbmdnU0lkbp3T-TNnZ2dnUVZ_hadnZ2d@earthlink.com>
In reply to#16607
Thomas 'PointedEars' Lahn wrote:
...
> BTW, your quoting style is suboptimal.  Omissions, if any, should be 
> indicated at the same quotation level as the text from which text has been 
> omitted.  `[...]' or (typographically correct) `[…]' should be used to 
> indicate omission, to distinguish it from an ellipsis in the quoted text.

Interesting. I've been posting, using similar quoting style, in various
USENET newsgroups, for over 20 years. You are the very first person to
comment on this.

Patricia

[toc] | [prev] | [next] | [standalone]


#16616

From"Evertjan." <exxjxw.hannivoort@inter.nl.net>
Date2012-10-13 23:59 +0200
Message-ID<XnsA0EBF4177955Deejj99@194.109.133.133>
In reply to#16608
Patricia Shanahan wrote on 13 okt 2012 in comp.lang.javascript:

> Thomas 'PointedEars' Lahn wrote:
> ...
>> BTW, your quoting style is suboptimal.  Omissions, if any, should be 
>> indicated at the same quotation level as the text from which text has
>> been omitted.  `[...]' or (typographically correct) `[ƒ İ]' should be
>> used to indicate omission, to distinguish it from an ellipsis in the
>> quoted text. 
> 
> Interesting. I've been posting, using similar quoting style, in
> various USENET newsgroups, for over 20 years. You are the very first
> person to comment on this.

Could be that most of us are oldfassionly polite to you?

Even so, 20 years of dejavue is a long stretch even for an active 
usenetter.

-- 
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

[toc] | [prev] | [next] | [standalone]


#16620

FromDr J R Stockton <reply1241@merlyn.demon.co.uk.invalid>
Date2012-10-13 19:31 +0100
Message-ID<jkEQRiKMObeQFw8b@invalid.uk.co.demon.merlyn.invalid>
In reply to#16573
In comp.lang.javascript message <CbGdnbfKl-UJW-rNnZ2dnUVZ_vydnZ2d@earthl
ink.com>, Fri, 12 Oct 2012 08:28:19, Patricia Shanahan <pats@acm.org>
posted:

>RobG wrote:
>...
>> 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.
>...
>
>It's perhaps worth emphasizing the fact that the ties go to nearest even
>style of rounding is the normal rounding mode in JavaScript arithmetic.
>It is what you get if you add two numbers, and the exact sum has more
>than 53 bits, ignoring leading and trailing zeros.

Forced rounding because 53 bits is insufficient and voluntary rounding
by explicitly calling a rounding routine are two quite distinct cases,
and neither should influence the other.

-- 
 (c) John Stockton, nr London, UK.  Mail via homepage.  Turnpike v6.05  MIME.
  Web  <http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms and links;
  Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc.

[toc] | [prev] | [next] | [standalone]


#16632

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2012-10-14 11:09 +0000
Message-ID<k5e6h9$2cg$3@dont-email.me>
In reply to#16570
On Thu, 11 Oct 2012 21:46:33 -0700, RobG wrote:

> On Friday, 12 October 2012 06:16:03 UTC+10, Danny  wrote:

>> 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.

I suspect that was the case that Danny was referring to.

Normally, for any "whole number" x.0, I would expect decimal fractions in 
the range (x.0 - 0.5) .. (x.0 + 0.49999999999999999999999999..) to round 
to x.

I think this is what you get if your rounding function f(x) is 
{return Math.floor(x+0.5);}

I think (1) it's probably better to keep your numbers away from the cases 
where errors may occur, and (2) if you want to process numbers with that 
much precision, don't use javascript.

Rgds

Denis McMahon

[toc] | [prev] | [next] | [standalone]


#16593

FromDr J R Stockton <reply1241@merlyn.demon.co.uk.invalid>
Date2012-10-12 22:48 +0100
Message-ID<t1rDlhGwAJeQFwdA@invalid.uk.co.demon.merlyn.invalid>
In reply to#16549
In comp.lang.javascript message <6dc8cb55-c29c-4bb2-ab6d-d9a9447cffd4@go
oglegroups.com>, Wed, 10 Oct 2012 19:52:09, RobG <rgqld@iinet.net.au>
posted:

Adherence to the 72-character convention would be appreciated.

>The largest contiguous integer (i.e. the largest of the continuous
>sequence that can be represented exactly) in Javascript is 2^53, so it
>might be expected that integers below this value should not exhibit
>precision errors.
>
>The ES5 specification for Math.round(x)[1] says that:
>
>  "If x is already an integer, the result is x"

Agreed.

>and that:
>
>  "The value of Math.round(x) is the same as the
>   value of Math.floor(x+0.5)"

Not really agreed.  That is part of a Note, which should be explicative
and is not normative.  The second part of the Note also seems wrong; +0
and -0 are distinguishable, but have the same value.


>So one might expect Math.round(x) to simply return x for all integers
>up to 2^53. But if the Math.floor criterion is applied, the limit is
>2^52 (4503599627370496), so these criteria conflict for odd numbers
>between 2^52 and 2^53.
>
>Browsers must choose which criterion they will respect, naturally some
>of the more popular ones have chosen differently.
>
>e.g. in Firefox and Chrome:
>
>    Math.round(4503599627370496)       -> 4503599627370496
>    Math.round(4503599627370497)       -> 4503599627370497
>    Math.floor(4503599627370497 + 0.5) -> 4503599627370498
>
>which satisfies the first criterion, but fails the second.
>
>In IE and Opera:
>
>    Math.round(4503599627370496)       -> 4503599627370496
>    Math.round(4503599627370497)       -> 4503599627370498
>    Math.floor(4503599627370497 + 0.5) -> 4503599627370498
>
>which satisfies the second criterion but not the first.
>
>There are arguments to support both cases but there is no conclusive
>agrument one way or the other. It seems to me that this can't be called
>a bug in implementations, but is a specification error for providing
>incompatible requirements.

Only the first case is right; it agrees with the normative part.
Math.round of an integer should certainly return the identical integer
(and not just an integer of the same value).

>Is it possible to meet both criteria within the bounds of javascript numbers?
>
>Is there some overwhelmingly good argument to support one criterion and
>not the other?

The normative way makes sense, the other does not.

>1. http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.15
>2. http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.6
                                                    15.8.2.9 ???


Entered into <http://www.merlyn.demon.co.uk/js-flaws.htm#Auto>.  Safari
5.1.7 correctly matches Firefox & Chrome.

-- 
 (c) John Stockton, nr London, UK.   E-mail, see Home Page.    Turnpike v6.05.
 Website  <http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
 PAS EXE etc. : <http://www.merlyn.demon.co.uk/programs/> - see in 00index.htm
 Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web