This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4637. to_chars with default representation specifies e for zero

Section: 28.2.2 [charconv.to.chars] Status: New Submitter: Tianjiao Yin Opened: 2026-11-05 Last modified: 2026-11-07

Priority: Not Prioritized

View other active issues in [charconv.to.chars].

View all other issues in [charconv.to.chars].

View all issues with New status.

Discussion:

In 28.2.2 [charconv.to.chars] paragraph 7 (as added by P3505R4), the rule choosing between fixed (f) and scientific (e) notation for the default floating-point representation reads:

The conversion specifier is f if the absolute value of value is in the range [l, u), where l is the smallest value larger than or equal to 10-4 that is representable by T and u is the largest value smaller than or equal to numeric_limits<T>::radixnumeric_limits<T>::digits + 1 rounded down to the nearest power of 10 representable by T, otherwise e.

Because 0 < 10^-4, zero is strictly outside [l, u) and falls into the fallback branch ("otherwise e"). Taken literally, formatting 0.0 or -0.0 with the default representation (and by extension std::format("{}", 0.0)) would produce scientific notation ("0e+00" or "-0e+00").

In C++26 and earlier, 0.0 formatted as "0" under the shortest-representation rule. While P3505R4) intended to adopt a range-based choice matching Python and Rust, replacing the shortest-length rule with [l, u) inadvertently caused zero to fall through to scientific notation.

[2026-11-07; Daniel comments]

This issue has considerable wording overlap with LWG 4602(i).

Proposed resolution:

This wording is relative to N5054.

  1. Modify 28.2.2 [charconv.to.chars] as indicated:

    to_chars_result to_chars(char* first, char* last, floating-point-type value);
    

    -7- Effects: Let T be floating-point-type. value is converted to a string in the style of printf in the "C" locale. The conversion specifier is f if the absolute value of value is zero or in the range [l, u), where l is the smallest value larger than or equal to 10-4 that is representable by T and u is the largest value smaller than or equal to std::numeric_limits<T>::radixstd::numeric_limits<T>::digits + 1 rounded down to the nearest power of 10 representable by T, otherwise e.

    -8- Throws: Nothing.