mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-08 23:58:31 +08:00
stdio-common: Keep trailing zeros where %#g rounds into a new decade (BZ 34578)
The g and G conversions choose between the f and e styles according to
the exponent the value has once rounded to the requested number of
significant digits. Where the value is small enough for the f style but
rounding then carries into a new decade, printf_fp rewrites the digits
it has already produced into the e style, recomputing along the way how
many fractional digits the leading digit now leaves room for.
FRACDIG_MIN, which the alternative form sets to the number of fractional
digits that have to be retained rather than stripped, was left behind at
the value computed for the f style. Where the value filled the whole
integer part that is zero, so all the fractional digits were then
stripped from a result the '#' flag requires to keep them:
printf ("%#.2g", 99.9) gave "1.e+02" rather than "1.0e+02"
printf ("%#g", 999999.9) gave "1.e+06" rather than "1.00000e+06"
Update FRACDIG_MIN along with FRACDIG_MAX. Without the alternative form
nothing retains trailing zeros, so the outcome is unchanged there.
None of the values the conversion tests iterate over round this way, so
add one that does at a precision they cover.
Tested on x86_64-linux-gnu.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
committed by
Adhemerval Zanella
parent
1cd5d3bba7
commit
19e50d60ec
@@ -896,6 +896,11 @@ __printf_fp_buffer_1 (struct __printf_buffer *buf, locale_t loc,
|
||||
fracdig_no += intdig_no;
|
||||
intdig_no = 1;
|
||||
fracdig_max = intdig_max - intdig_no;
|
||||
if (info->alt)
|
||||
/* The alternative form retains trailing zeros, and
|
||||
the number of fractional digits it has to retain
|
||||
has just changed along with FRACDIG_MAX. */
|
||||
fracdig_min = fracdig_max;
|
||||
++p.exponent;
|
||||
/* Now we must print the p.exponent. */
|
||||
p.type = isupper (info->spec) ? 'E' : 'e';
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
typedef double type_t;
|
||||
static const type_t vals[] =
|
||||
{ -HUGE_VAL, -DBL_MAX, -DBL_MIN, -0.0, -NAN, NAN, 0, DBL_MIN,
|
||||
DBL_MAX, HUGE_VAL };
|
||||
99.9, DBL_MAX, HUGE_VAL };
|
||||
static const char length[] = "";
|
||||
|
||||
#include "tst-printf-format-skeleton.c"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
typedef long double type_t;
|
||||
static const type_t vals[] =
|
||||
{ -HUGE_VAL, -LDBL_MAX, -LDBL_MIN, -0.0, -NAN, NAN, 0, LDBL_MIN,
|
||||
LDBL_MAX, HUGE_VAL };
|
||||
99.9L, LDBL_MAX, HUGE_VAL };
|
||||
static const char length[] = "L";
|
||||
|
||||
#ifndef TIMEOUT
|
||||
|
||||
Reference in New Issue
Block a user