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: C11 / C17
Status: Fixed
Fixed in: C23
Converted from: n2396.htm
This is about the issue raised by Joseph Myers in email SC22WG14.14285:
C11 defines
DECIMAL_DIGas "number of decimal digits, n, such that any floating-point number in the widest supported floating type with pmax radix b digits can be rounded to a floating-point number with n decimal digits and back again without change to the value," and then gives a formula.Is it OK for the value of
DECIMAL_DIGto be larger than given by the formula? Such a value would still seem to meet the textual description, though being suboptimal.This is an issue for implementing TS 18661-3 when that involves types wider than
long double. In C11, "real floating type" meansfloat,doubleorlong double(6.2.5#10) (and then those types plus the three complex types are defined to be the floating types). TS 18661-3 is supposed to be compatible with C11, so that an implementation can conform to both simultaneously. The definition ofDECIMAL_DIGin TS 18661-3 covers all supported floating types and non-arithmetic encodings. And that's not conditional on__STDC_WANT_IEC_60559_TYPES_EXT__. So in an implementation of TS 18661-3 that supports_Float128,DECIMAL_DIGmust be big enough for_Float128, even if__STDC_WANT_IEC_60559_TYPES_EXT__is not defined when<float.h>is included. And that's only compatible with C11 (iflong doubleis narrower than_Float128) if C11 allowsDECIMAL_DIGto be larger than given by the formula.
Agreed. The current specification for DECIMAL_DIG in TS 18661-3 is
incompatible with C11, as explained.
The suggested Technical Corrigendum below allows DECIMAL_DIG to be larger than
the value of the given formula. Thus an implementation that supports a floating
type wider than long double, for example a wide type in TS 18661-3, could
define DECIMAL_DIG to be large enough for its widest type and still conform as
a C implementation without extensions.
Where DECIMAL_DIG is used to determine a sufficient number of digits, this
change might lead to conversions with more digits than needed and with more
digits than would have been used without the change. However, programs wishing
the minimal sufficient number of digit are better served by the type-specific
macros FLT_DECIMAL_DIG, etc.
We considered the alternative of changing TS 198661-3 to make DECIMAL_DIG
dependent on __STDC_WANT_IEC_60559_TYPES_EXT__. But this could lead to errors
resulting from separately compiled parts of a program using inconsistent values
of DECIMAL_DIG.
In 5.2.4.2.2#11, change the bullet defining DECIMAL_DIG from:
— number of decimal digits, n, such that any floating-point number in the widest supported floating type with pmax radix b digits can be rounded to a floating-point number with n decimal digits and back again without change to the value,
< … formula … >
to:
— number of decimal digits, n, such that any floating-point number in the widest supported floating type with pmax radix b digits can be rounded to a floating-point number with n decimal digits and back again without change to the value, at least
< … formula … >
Comment from WG14 on 2019-05-03:
Oct 2016 meeting
The committee agrees with the recommendation. The following example was solicited and provided for a committee response.
(The committee’s Proposed Committee Response and Proposed Technical Corrigendum have been superceded)
Apr 2017 meeting
The committee’s Proposed Committee Response and Proposed Technical Corrigendum from the last meeting was discussed and a new paper N2108 by the WG14 Floating Point study group was written and discussed at some length. After due consideration the committee agreed with their conclusion that
DECIMAL_DIGcould not in fact be implemented properly, and adopted their Suggested Technical Corrigendum below. For reference, the committee's previous direction can be found in N2109 and has been elided in this document.
Oct 2017 meeting
A proposed change was adopted.
Apr 2018 meeting
Alternative input to the Proposed Change was presented in paper N2211 by the C Floating Point working group.
These changes were, however, not reviewed by the Committee.
Oct 2018 meeting
Alternative input to the Proposed Change was presented in paper N2211 by the C Floating Point working group.
N2108 suggested obsolescing
DECIMAL_DIG, as part of the resolution of CR 501. This document updates the suggested CR in N2108 to eliminate references in C11 toDECIMAL_DIG, and to clarify. Changes below (along with changes to TS 18661) were identified in N2211.The Floating Point Study Group was requested to extract the changes for C from N2211 and present them separately. This was done and presented (without change) in paper N2253 and these changes were accepted by the committee as the proposed resolution to this issue.
In 7.31, add a subclause:
7.31.x Mathematics
<math.h>Use of the
DECIMAL_DIGmacro is an obsolescent feature. A similar type-specific macro, such asLDBL_DECIMAL_DIGcan be used instead.
In 5.2.4.2.2#11, in the bullet defining DECIMAL_DIG, attach a footnote to the
wording:
DECIMAL_DIG
where the footnote is:
*) See ‘‘future library directions’’ (7.31.x).
In 5.2.4.2.2#14, change:
[14] Conversion from (at least)
doubleto decimal withDECIMAL_DIGdigits and back should be the identity function.
to:
[14] Conversion between real floating type and decimal character sequence with at most T
_DECIMAL_DIGdigits should be correctly rounded, where T is the macro prefix for the type. This assures conversion from real floating type to decimal character sequence with T_DECIMAL_DIGdigits and back, using to-nearest rounding, is the identity function.
In 5.2.4.2.2#16, in the list of macro values in EXAMPLE 2, omit:
DECIMAL_DIG 17
In 5.2.4.2.2#16, at the end of EXAMPLE 2, omit:
If a type wider than
doublewere supported, thenDECIMAL_DIGwould be greater than 17. For example, if the widest type were to use the minimal-width IEC 60559 double-extended format (64 bits of precision), thenDECIMAL_DIGwould be 21.
In 7.21.6.1#13 and 7.29.2.1#13, change:
[13] For
e,E,f,F,g, andGconversions, if the number of significant decimal digits is at mostDECIMAL_DIG, then the result should be correctly rounded.283) If the number of significant decimal digits is more thanDECIMAL_DIGbut the source value is exactly representable withDECIMAL_DIGdigits, then the result should be an exact representation with trailing zeros. Otherwise, the source value is bounded by two adjacent decimal strings L < U, both havingDECIMAL_DIGsignificant digits; the value of the resultant decimal string D should satisfy L ≤ D ≤ U, with the extra stipulation that the error should have a correct sign for the current rounding direction.
to:
[13] For
e,E,f,F,g, andGconversions, if the number of significant decimal digits is at most the maximum value M of the T_DECIMAL_DIGmacros (defined in<float.h>), then the result should be correctly rounded.283) If the number of significant decimal digits is more than M but the source value is exactly representable with M digits, then the result should be an exact representation with trailing zeros. Otherwise, the source value is bounded by two adjacent decimal strings L < U, both having M significant digits; the value of the resultant decimal string D should satisfy L ≤ D ≤ U, with the extra stipulation that the error should have a correct sign for the current rounding direction.
In 7.22.1.3#9 and 7.29.4.1.1#9, change:
[9] If the subject sequence has the decimal form and at most
DECIMAL_DIG(defined in<float.h>) significant digits, the result should be correctly rounded. If the subject sequence D has the decimal form and more thanDECIMAL_DIGsignificant digits, consider the two bounding, adjacent decimal strings L and U, both havingDECIMAL_DIGsignificant digits, such that the values of L, D, and U satisfy L ≤ D ≤ U. The result should be one of the (equal or adjacent) values that would be obtained by correctly rounding L and U according to the current rounding direction, with the extra stipulation that the error with respect to D should have a correct sign for the current rounding direction.294)
to:
[9] If the subject sequence has the decimal form and at most M significant digits, where M is the maximum value of the T
_DECIMAL_DIGmacros (defined in<float.h>), the result should be correctly rounded. If the subject sequence D has the decimal form and more than M digits, consider the two bounding, adjacent decimal strings L and U, both having M significant digits, such that the values of L, D, and U satisfy L ≤ D ≤ U. The result should be one of the (equal or adjacent) values that would be obtained by correctly rounding L and U according to the current rounding direction, with the extra stipulation that the error with respect to D should have a correct sign for the current rounding direction.294)
In 7.22.1.3 footnote 294 and 7.29.4.1.1 footnote 345, change:
DECIMAL_DIG, defined in<float.h>, should be sufficiently large that L and U will usually round to the same internal floating value, but if not will round to adjacent values.
to:
M is sufficiently large that L and U will usually correctly round to the same internal floating value, but if not will correctly round to adjacent values.
In F.5, omit footnote 361:
If the minimum-width IEC 60559 extended format (64 bits of precision) is supported,
DECIMAL_DIGshall be at least 21. If IEC 60559 double (53 bits of precision) is the widest IEC 60559 format supported, thenDECIMAL_DIGshall be at least 17. (By contrast,LDBL_DIGandDBL_DIGare 18 and 15, respectively, for these formats.)
The following change is needed only if TS 18661-1 (with CR 20) is not incorporated into C.
In F.5, replace::
[1] Conversion from the widest supported IEC 60559 format to decimal with DECIMAL_DIG digits and back is the identity function.361)
[2] Conversions involving IEC 60559 formats follow all pertinent recommended practice. In particular, conversion between any supported IEC 60559 format and decimal with
DECIMAL_DIGor fewer significant digits is correctly rounded (honoring the current rounding mode), which assures that conversion from the widest supported IEC 60559 format to decimal withDECIMAL_DIGdigits and back is the identity function.
with:
[1] Conversions involving IEC 60559 formats follow all pertinent recommended practice. Conversion between any supported IEC 60559 format and decimal character sequence with M or fewer significant digits is correctly rounded (honoring the current rounding mode), where M is the maximum value of the T
_DECIMAL_DIGmacros (defined in<float.h>). Conversion from any supported IEC 60559 format to decimal character sequence with at least T_DECIMAL_DIGdigits (for the corresponding type) and back, using to-nearest rounding, is the identity function.
and renumber the subsequent paragraph.