# ES3.1 Proposal Working Draft - decimal support

Mike Cowlishaw MFC at uk.ibm.com
Thu Feb 21 01:25:50 PST 2008

```[I have just subscribed to es4-discuss at mozilla.org, but haven't yet found
the archives, so I may be missing some content, here.]

Brendan Eich <brendan at mozilla.org> wrote on 20/02/2008 22:39:38:

> On Feb 20, 2008, at 1:00 PM, Adam Peller wrote:
>
> > >Each of us has some pet addition we think would be a great
> > >the language. "const", "decimal", getters and setters, destructing
> > >assignment -- all these have come up just this morning!. Each of
> > >these
> > >makes the language larger and more complex, imposing a general
> > >diffuse
> > >cost on everyone.
> >
> > Mark, as I recall, the discussion at the March meeting in Newton
> > involved implementing decimal arithmetic in ES3.1 to *replace* the
> > floating point implementation in ES3, thus "no new syntax". Yes,
> > this would have unexpected results for those who actually have code
> > logic which expects a value of "46.19" pounds, in Mike's example
> >
>
> I'm not sure what was to blame for that Manchester car-park example --
> IEEE double can multiply 4.2 by 11 and round properly:
>
> js> 11*4.2
> 46.2
> js> (11*4.2).toFixed(2)
> 46.20
>
> Cc'ing Mike in case he knows the full story (it's a fun example and
> useful real-world evidence of something, I bet).

This example is a classic one because there is no reason for the
application writer to even consider using explicit rounding here.  The
calculation is taking what appears to be an exact currency amount (4.20)
and multiplying that by an integer (11) which should give an exact result
(46.20).  To put it another way, in decimal floating point, the 4.20 is
held as 420E-2 (420 times 10 to the power of -2) and the 11 would be the
integer 11E+0.  The 754r rules of multiplication multiply the coefficients
and add the exponents, giving 4620E-2, which is exactly the right answer
(and what one would get on paper).  No rounding required or necessary.

In general, when writing an application using decimals (especially where
financials are involved), rounding should never be implied implicitly or
explicitly (including 'formatting' for display) unless it's called for in
the algorithm (typically after division) or by tax rules etc.  That's
because the required rounding mode might change, or the underlying data
might change (a tax rate might get a couple more digits, etc.) and
something that appeared to be a rounding that should not affect the result
might suddenly start rounding off digits.  One definitely doesn't want to
hard-code scales (exponents) and modes into the program.  In IEEE 754
terms, the Inexact flag should normally never be set except after explicit
rounding or division (or subsequent use of an inexact, and hence
full-precision, result).

For a bit more background in the complexities here, see the example from
SAP in:

http://www-03.ibm.com/support/techdocs/atsmastr.nsf/5cb5ed706d254a8186256c71006d2e0a/c519746ca770109f86257363004a5bd9/\$FILE/DFP_PW6_in_SAP_NetWeaver_0907.pdf

(Sorry about the long URL!)  There's a trivial example of rounding in
decimal on page 3.  The corresponding code to do it using binary FP is on
page 5.

> > but the benefits here seemed to far outweigh this discrepancy.
>
> No, sorry -- too much real-world code, not to mention synthetic
> benchmarks, depend on hardware-implemented floating point. There are
> also enough numerical and semi-numerical JS apps around that count on
> IEEE-754 double precision quirks that we cannot change the number
> type without opt-in versioning.

I think the point here is that it *could* be done without new syntax --
whether that's the best way or not is in some sense 'a detail', although a
devilish one.  As Brendan says, there are many ways of doing this; new
syntax such as 'use decimal' seems quite reasonable.  Meta-data (such as
opt-in versioning or pragmas) is arguably not 'new syntax', and is also
another way of approaching this.

> > I can't speak to the technical level of detail that Mike can, but
> > at a high level it's seen as a bug by the vast majority of users,
> > and for all practical purposes, that's what it is.
>
> Yes, I keep reciting its status as the most duplicated JavaScript
> Engine bug on file at https://bugzilla.mozilla.org/ (to wit, https://
> bugzilla.mozilla.org/show_bug.cgi?id=5856). But that does not mean it
> can be fixed with an incompatible change. The thinking for ES4 was to
> support a 'use decimal' pragma, for block- or wider-scoped explicit
> "opt in". This proposal,
>
> http://wiki.ecmascript.org/doku.php?id=proposals:decimal
>
> with this discussion page
>
> http://wiki.ecmascript.org/doku.php?id=discussion:decimal
>
> stood for a while, but was superseded by
>
> http://bugs.ecmascript.org/ticket/222
>
> And I believe there was an email conversation or two in which Mike
> was included. At this point, I would find it helpful to summarize the
> thinking on usable alteratives for decimal in ES4, and try to reach a
> consensus in this list. But again, I do not believe we can change the
> number type incompatibly -- that ship sailed in 1995. :-(

(I hadn't seen the ticket, just the earlier discussions -- thanks [should
really have been 10, 100, or 1000, not 222 :-)].)

The 'use decimal' is definitely a perfectly reasonable way to go.  It also
has the advantage that if there's code that expects/is required to work in
decimal but is accidentally run under an 'old' version of ECMAScript one
will get some sort of indication of a problem, rather than quietly get

Separately from the decimal discussion, I am a bit confused at how ES3.x
or ES4 is migrated to from ES3.  If the syntax cannot change then that
implies that the semantics change without any indication in the syntax.
That would mean that existing scripts would work differently than before.
Surely that pretty much requires some meta-notation (such as opt-in
versioning)?

Mike

Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU

```