diff --git a/dtoa.c b/dtoa.c index ac1be8d..14b6605 100644 --- a/dtoa.c +++ b/dtoa.c @@ -1505,8 +1505,10 @@ double js_atod(const char *str, const char **pnext, int radix, int flags, } /* Use the extra digits for rounding if the base is a power of - two. Otherwise they are just truncated. */ - if (radix_bits != 0 && extra_digits != 0) { + two. Otherwise use them as a sticky bit so that round-half-to-even + rounds correctly when there are non-zero digits beyond the + precision we kept. */ + if (extra_digits != 0) { tmp0->tab[0] |= 1; } diff --git a/tests/test_builtin.js b/tests/test_builtin.js index 14bcc06..9d9ac31 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -398,6 +398,12 @@ function test_number() assert((1.3).toString(7), "1.2046204620462046205"); assert((1.3).toString(35), "1.ahhhhhhhhhm"); + + /* parsing must use digits beyond max_digits as a sticky bit so + that round-half-to-even rounds in the correct direction. + https://github.com/bellard/quickjs/issues/452 */ + assert(+"100000000000000000000000.000000000000001", + 1.0000000000000001e+23); } function test_eval2()