A directive to solve the JavaScript arithmetic precision issue
David Bruant
david.bruant at labri.fr
Mon Aug 15 13:58:43 PDT 2011
Le 15/08/2011 21:33, Brendan Eich a écrit :
> On Aug 15, 2011, at 10:33 AM, David Bruant wrote:
>> I don't know if it has been proposed already, but what about a
>> directive? Code could look like:
>> ------
>> "use precise arithmetic"; // choose any other name you'd like here
>>
>> var a = 0.1 + 0.2; // 0.3 // FINALLY!
>> ------
>> What number format should be used? I have no expertise whatsoever in
>> that domain, so i'll let people who do talk.
>> In his talks, Douglas Crockford mentions that the fact that JS has one
>> number type is a good thing, so, maybe that choosing a unique
>> replacement should be the best thing.
>> Alternatively, the directive could be "parametrized" with number formats
>> ("use number IEEE XYZ").
> You will not get premature standardization past TC39 on this front. Our agreement when decimal missed ES3.1 in 2008 fall (the Kona meeting) was to work on value types so that new numeric types could be implemented in-language.
That's an interesting piece of information. If I understand it
correctly, it would imply that the expression "0.1+0.2" will never be
equal to 0.3 in a JavaScript program (even with any sort of opt-in
(@type versionning, directive, pragma...)). The best thing i can think
of is wrapping my numbers to create values out of them. So,
"wrap(0.1)+wrap(0.2)" can be equal to 0.3.
(Tell me if there is a part i misunderstand or forget)
Consequently, in order to have accurate arithmetic, i can:
- wrap by hand my numbers (which doesn't scale well if i want to apply
it to current JS files)
- use a compiler/transpiler to wrap numbers automatically.
But it would be hard to tell automatically which numbers should be
wrapped and which should not. Wrapping all numbers could have annoying
performance issues.
- use some combining approach (interactive tool, heuristics...)
Also, from what i understand, typeof( wrap(0.1)+wrap(0.2) ) could not be
"number".
A directive may not solve every problem caused by numeric types, but it
would solve the problem of making current code work with precise
arithmetic at a small cost (from the developer side).
> Today, that means module-encapsulated implementations, and (for usability) value types for operator syntax. But value types as you note are not in ES6.
>
> Sketching a directive solves *nothing*. Would Math.sin change to use the new numeric type? If not, why not? If so, how?
In ES5, Math.sin and most other Math functions are specified as "Returns
an *implementation-dependent* approximation to the sine of x.", so I do
not consider this as a concern. Regardless of underlying number
representation, Math.sin returns a approximation of the sine of the
argument.
I guess I should return the question: how would Math.sin behave with a
value proxy? This question stands for any in-language representation.
Since the numeric type is defined in-language, there is not the
"regardless of underlying numeric representation" trap that i used above
since the representation is not /under/lying.
Will in-language values have to define a behavior for each Math
function? What when new Math functions are added?
Will in-language values have to provide a "default IEEE double value" to
work with native Math functions?
> Worse, what about calls from within the extent of the "use precise arithmetic" pragma to outside of that scope? Of course we can't have dynamic scope, but what *types* of parameters pass across the barrier? Do precise numbers coerce with loss of precision to IEEE double?
I agree that this is an issue.
But a first answer would be that if you really care about precision, you
will be careful of using only precise arithmetic scripts to not be
bothered by the dual-mode and issues that could come with it (loss of
precision).
If you do not care very much about precision, either you do not use the
directive or being coerced to non-precise numbers is not an issue for
you, so coercion sounds like a good compromise
> Rather than bikeshed directive syntax, which solves nothing, we need more design and implementation work on value types, specifically new numeric types.
>
> Worse, we may need the "big red switch" on the side of a clique of addressable global objects, so one can opt *everything* into the precise numeric type, including Math, Number, canvas, WebGL, etc. And doing so may break (or at least terribly slow down) canvas, WebGL, etc. So the big red switch may be a pipe dream.
>
> If so, then the problem becomes how to use different numeric types conveniently. Per our TC39 agreement
Are there notes of the 2008 Kona meeting?
What were the arguments leading to this agreement?
David
> this must mean value types, prototype modules implementing numeric value types, user testing, and experiments with coercion rules. This is hard, it takes time.
>
> If we had this effort further along, we could haggle over directive syntax. Right now, doing so is putting cart before horse.
>
> Let's work on the hard parts first.
>
> /be
>
>
>> A directive would have the same benefits than use strict which is to not
>> break existing code in platform that do not support this directive. With
>> a relevant arithmetic test, feature testing will be doable, enabling to
>> determine whether or not a given platform can execute accurate
>> arithmetic (and taking action if not).
>>
>> It would also have the benefit to fix arithmetic for existing script (at
>> the cost of adding a directive on top).
>>
>> Thoughts?
>>
>> David
>>
>> [1] http://blip.tv/jsconf/nodeconf-2011-nodecommit-panel-edited-5420208
>> [2] http://blip.tv/jsconf/jsconf2011-andrew-paprocki-5455215
>> [3] http://wiki.ecmascript.org/doku.php?id=strawman:value_proxies
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
More information about the es-discuss
mailing list