toExponential rounding error
Categories
(Core :: JavaScript: Standard Library, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox87 | --- | fixed |
People
(Reporter: swediomurital, Assigned: jandem)
References
(Blocks 2 open bugs)
Details
Attachments
(5 files)
Comment 1•12 years ago
|
||
![]() |
||
Updated•11 years ago
|
Comment 2•9 years ago
|
||
Comment 3•9 years ago
|
||
Comment 4•7 years ago
|
||
Updated•7 years ago
|
Comment 5•5 years ago
|
||
Hey folks, just following up here since it's been a while since there's been any activity on this. It looks like the fix above in dtoa.c
fixes the tests for this, and as far as I can tell it doesn't cause any other regressions, although I'm not sure how best to handle the in-tree copy of this. Any thoughts? I have a patch with the previously mentioned changes, but I didn't change the copy yet since I wasn't sure if those files were intentionally duplicated.
Comment 6•5 years ago
|
||
Updated•5 years ago
|
Comment 7•5 years ago
|
||
Searchfox indicates dtoa
is only called by Number.prototype.to{Fixed,Exponential,Precision}
and by our internal JSONPrinter
used only for CacheIR spew. So, we need only care about this change with respect to three algorithms.
I'm attempting to review this now. It is going to be awhile. dtoa.c
is a wretched hive of scum and villainy that either needs to be drastically cleaned up and commented, rewritten in Rust (with exceptionally few unsafe
blocks), or nuked from orbit and the ground salted and replaced with some modern equivalent that is maintained and understandable (even at mild expense of performance, seeing as throughput of float->string operations ought not be a real-world limiting factor and safety/correctness are more important in these circumstances).
Comment 8•5 years ago
•
|
||
Unfortunately bug 450392 and bug 384244 imply our copy is heavily modified so we can't just update from upstream, which has in fact been fixing things for years: http://www.netlib.org/fp/changes
The relevant code upstream (http://www.netlib.org/fp/dtoa.c) reads:
dval(&u) += dval(&u);
#ifdef ROUND_BIASED
if (dval(&u) >= ds)
#else
if (dval(&u) > ds || (dval(&u) == ds && L & 1))
#endif
Which suggests that the patch here could lose the second half of the condition, but perhaps also that there's a bunch more ROUND_BIASED fixes that would need to be applied.
Comment 9•5 years ago
|
||
It looks like we have a more modern dtoa in https://searchfox.org/mozilla-central/source/mfbt/double-conversion/double-conversion
Comment 10•5 years ago
|
||
dtoa.c is a wretched hive of scum and villainy that either needs to be drastically cleaned up and commented, rewritten in Rust
It appears you wishes have been granted given that we have third_party/rust/dtoa
.
That said, js/src/util/DoubleToString.cpp seems to require knowledge of dtoa internals, so at this point this thing is too scary for me to touch.
Comment 11•5 years ago
|
||
Also see https://news.ycombinator.com/item?id=26035495 for a survey of recent work.
dtoa.c is to JS as water is to the Earth: you can (probably) make it work with other substances, but try it at your peril.
Assignee | ||
Comment 12•5 years ago
|
||
I think we should move this code to DoubleToStringConverter::ToExponential
. That's what other JS engines are using and it fixes the bug for me (and passes all shell tests).
Assignee | ||
Comment 13•5 years ago
|
||
So looking at what JSC does:
- For
toExponential
, they useDoubleToStringConverter::ToExponential
. - For
toPrecision
, they usenumberToStringFixedPrecision
which callsDoubleToStringConverter::ToPrecision
. - For
toFixed
, they usenumberToStringFixedWidth
which ends up callingDoubleToStringConverter::ToFixed
.
The annoying part is that ToFixed
supports precision (requested_digits
) up to 60, whereas JS requires up to 100. JSC made changes to the double-conversion code to support this. We however made other changes to that code last week.
So long story short: I think we can use double-conversion, but for toFixed
with large precision values we either need to fall back to dtoa or change the code.
Assignee | ||
Comment 14•5 years ago
|
||
This avoids a rounding issue in the old dtoa code.
Assignee | ||
Comment 15•5 years ago
|
||
Depends on D104519
Assignee | ||
Comment 16•5 years ago
|
||
We need to support values up to 100 for Number.prototype.toFixed
.
Depends on D104520
Assignee | ||
Comment 17•5 years ago
|
||
Depends on D104521
Assignee | ||
Comment 18•5 years ago
|
||
The patches move {toExponential, toPrecision, toFixed} from js_dtostr
to the double-conversion code in MFBT. After that the only caller of js_dtostr
is JSONPrinter::floatProperty
and that should be easy to fix in a follow-up.
I did some micro-benchmarking and the double-conversion code is a bit faster than the dtoa implementation.
Comment 19•5 years ago
|
||
Cool. I was planning to look into moving js to double-conversion soon, looks like I won't have to :)
Comment 20•5 years ago
|
||
Comment 21•5 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/d06ce5533326
https://hg.mozilla.org/mozilla-central/rev/2560c2763df0
https://hg.mozilla.org/mozilla-central/rev/613260ab04e0
https://hg.mozilla.org/mozilla-central/rev/86cdeb4f7d76
Description
•