Consider the following printf instruction:
printf("%# 01.1g", 9.8);
what should it print?
I'm reading the description of the g specifier on cppreference.com, which says (text for G
removed):
converts floating-point number to decimal or decimal exponent notation depending on the value and the precision.
For the g conversion style conversion with style e or f will be performed.
Let P equal the precision if nonzero, 6 if the precision is not specified, or 1 if the precision is 0. Then, if a conversion with style e would have an exponent of X:
- if P > X ≥ −4, the conversion is with style f and precision P − 1 − X.
- otherwise, the conversion is with style e and precision P − 1.
Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left.
In our case,
"%# 01.1e"
, yields 9.8e+00
(adjust the GodBolt program and you'll see).consequently, the conversion should be with style f and precision P - 1 - X = 1 - 1 - 0 = 0, i.e. "%# 01.0f"
, which yields 10.
.
... but that is not what glibc produces: I get 1.e01
, as can also be seen on GodBolt.
So,
This is a lack of clarity about “a conversion with style E
” and a discrepancy about what the precision means for E
and g
.
With E
, the precision is the number of digits to appear after the decimal point, per C 2018 7.21.6.1 4. With g
, the precision is the maximum number of significant digits. Those differ; E
has an additional digit before the decimal point, giving a total of one more digit than its nominal “precision.”
Thus, in considering how to format 9.8 for %.1g
, we first consider how it would be formatted for %.0E
, not %.1E
, as both %.1g
and %.0E
request one digit, whereas %.1E
requests two digits. For %.0E
, “1e+01” would be produced. So the X, the exponent, is 1, not 0.