This issue has been automatically converted from the original issue lists and some formatting may not have been preserved.
Authors: WG14, Jim Thomas
Date: 2016-09-10
Reference document: N2077
Submitted against: Floating-point TS 18661 (C11 version, 2014-2016)
Status: Fixed
Fixed in: C23
Converted from: n2397.htm
The a
-style formatting specified in subclause 12.5 of TS 18661-2 is not an IEC
60559 conversion for cases where the formatting precision is less than the
length of the coefficient of the input. The specification entails an
intermediate rounding to the floating type of the input, which might overflow
resulting in a character sequence representation of infinity. IEC 60559
conversions to character sequences do not overflow, unless the language
over-restricts the exponent range for character sequence output, which C does
not.
Another undesirable aspect of the current specification is that in certain cases it produces results with more precision than given by a width modifier.
Here are some examples, showing the result of the intermediate conversion, with different behaviors for the current spec (“old”) and the spec in the suggested Technical Corrigendum below (“new”):
For _Decimal32
input x with representation (1, 9512345, 90) and specifier
...
%.3Ha
old: x -> (1, 9510000,
90) -> 9.510000e96
new: x -> (1, 951,
94) -> 9.51e96
%.2Ha
old: x -> (1, 9500000,
90) -> 9.500000e96
new: x -> (1, 95,
95) -> 9.5e96
%.1Ha
old: x ->
Inf -> inf
new: x -> (1, 1,
97) -> 1e97
Here’s another example:
For _Decimal32
input x with representation (1, 9512345, 86) and specifier ...
%.2Ha
old: x -> (1, 950,
90) -> 9.50e92
new: x -> (1, 95,
91) -> 9.5e92
The examples use a to-nearest rounding.
As the examples illustrate, the problematic cases for the current “old” spec occur because of the exponent range limitation of the format used for the intermediate conversion.
The suggested Technical Corrigendum below specifies formatting that is IEC 60559 conformant and which honors a width modifier. It does not change the numerical value of the result, except in overflow cases.
In 12.5, in the addition to 7.21.6.1#8 and 7.29.2.1#8, under a
,A
conversion
specifiers, change:
If the precision is present (in the conversion specification) and is zero or at least as large as the precision p (5.2.4.2.2) of the decimal floating type, the conversion is as if the precision were missing. If the precision is present (and nonzero) and less than the precision p of the decimal floating type, the conversion first obtains an intermediate result by rounding the input in the type, according to the current rounding direction for decimal floating-point operations, to the number of digits specified by the precision, then converts the intermediate result as if the precision were missing. The length of the coefficient of the intermediate result is the smallest number, at least as large as the formatting precision, for which the quantum exponent is within the quantum exponent range of the type (see 5.2.4.2.2a). The intermediate rounding may overflow.
to:
If the precision P is present (in the conversion specification) and is zero or at least as large as the precision p (5.2.4.2.2) of the decimal floating type, the conversion is as if the precision were missing. If the precision P is present (and nonzero) and less than the precision p of the decimal floating type, the conversion first obtains an intermediate result as follows, where n is the number of significant digits in the coefficient:
If n <= P, set the intermediate result to the input.
If n > P, round the input value, according to the current rounding direction for decimal floating-point operations, to P decimal digits, with unbounded exponent range, representing the result with a P-digit integer coefficient when in the form (s, c, q).
Convert the intermediate result in the manner described above for the case where the precision is missing.
In 12.5, in the addition to 7.21.6.1#8 and 7.29.2.1#8, in EXAMPLE 3, change the results:
9.54321e+93 9.5432e+93 9.543e+93 9.540e+93 9.500e+93 1.0000e+94 inf
to:
9.54321e+93 9.5432e+93 9.543e+93 9.54e+93 9.5e+93 1e+94 1e+97
Comment from WG14 on 2018-10-18:
Oct 2016 meeting
The committee agrees that this is a defect and accepts the Suggested Technical Corrigendum
Apr 2017 meeting
The paper N2126 provides an example that illustrates this change, and the committee agreed to accept this as an addendum to the Proposed Technical Corrigendum.
However, the committee is concerned that %a
behavior differs from binary
floating point and more review is needed. In particular, there were concerns
that for the decimal floating point types now the %a format specifier given with
a precision is the total number of significant digits, not the number of digits
after the decimal point as it has been for other data types.
In 12.5, in the addition to 7.21.6.1#8 and 7.29.2.1#8, under a
,A
conversion
specifiers, change:
If the precision is present (in the conversion specification) and is zero or at least as large as the precision p (5.2.4.2.2) of the decimal floating type, the conversion is as if the precision were missing. If the precision is present (and nonzero) and less than the precision p of the decimal floating type, the conversion first obtains an intermediate result by rounding the input in the type, according to the current rounding direction for decimal floating-point operations, to the number of digits specified by the precision, then converts the intermediate result as if the precision were missing. The length of the coefficient of the intermediate result is the smallest number, at least as large as the formatting precision, for which the quantum exponent is within the quantum exponent range of the type (see 5.2.4.2.2a). The intermediate rounding may overflow.
to:
If the precision P is present (in the conversion specification) and is zero or at least as large as the precision p (5.2.4.2.2) of the decimal floating type, the conversion is as if the precision were missing. If the precision P is present (and nonzero) and less than the precision p of the decimal floating type, the conversion first obtains an intermediate result as follows, where n is the number of significant digits in the coefficient:
If n <= P, set the intermediate result to the input.
If n > P, round the input value, according to the current rounding direction for decimal floating-point operations, to P decimal digits, with unbounded exponent range, representing the result with a P-digit integer coefficient when in the form (s, c, q).
Convert the intermediate result in the manner described above for the case where the precision is missing.
In 12.5, in the addition to 7.21.6.1#8 and 7.29.2.1#8, in EXAMPLE 3, change the results:
9.54321e+93 9.5432e+93 9.543e+93 9.540e+93 9.500e+93 1.0000e+94 inf
to:
9.54321e+93 9.5432e+93 9.543e+93 9.54e+93 9.5e+93 1e+94 1e+97
Add, as a new EXAMPLE,
#include <stdio.h>
int main(void) {
_Decimal32 x = 9512345e90df;
_Decimal32 x2 = 9512345e86df;
printf("%.3Ha\n", x); // New expected output: 9.51e96
printf("%.2Ha\n", x); // New expected output: 9.5e96
printf("%.1Ha\n", x); // New expected output: 1e97
printf("%.2Ha\n", x2); // New expected output: 9.5e92
return 0;
}