diff options
author | Zefram <zefram@fysh.org> | 2018-01-19 05:05:07 +0000 |
---|---|---|
committer | Zefram <zefram@fysh.org> | 2018-01-19 05:09:07 +0000 |
commit | 60fa46621ae5d0d44c802aedc205274584701fa0 (patch) | |
tree | 70bcd377015aeb2dc0bdd0321bbce0b70d7adb3f /sv.c | |
parent | 8c7aa727bdcea40fd6b4ffb9ca8bbf53c0fadb10 (diff) | |
download | perl-60fa46621ae5d0d44c802aedc205274584701fa0.tar.gz |
fix F0convert() on edge cases
The F0convert() function used to implement the %.0f format specifier
more cheaply went wrong on some edge cases. Its rounding went wrong
when the exponent is such that fractional values are not representable,
making the "+= 0.5" invoke floating point rounding. Fix that by only
invoking that rounding logic for values that start out fractional.
That fixes the output part of [perl #47602]. It also failed to emit the
sign for negative zero. Fix that by making it not apply to zero values.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 11 |
1 files changed, 7 insertions, 4 deletions
@@ -11057,12 +11057,15 @@ S_F0convert(NV nv, char *const endbuf, STRLEN *const len) assert(!Perl_isinfnan(nv)); if (neg) nv = -nv; - if (nv < UV_MAX) { + if (nv != 0.0 && nv < UV_MAX) { char *p = endbuf; - nv += 0.5; uv = (UV)nv; - if (uv & 1 && uv == nv) - uv--; /* Round to even */ + if (uv != nv) { + nv += 0.5; + uv = (UV)nv; + if (uv & 1 && uv == nv) + uv--; /* Round to even */ + } do { const unsigned dig = uv % 10; *--p = '0' + dig; |