c++floating-pointlanguage-lawyerprecisionstringification

Does std::to_chars ever really disambiguate using round_to_nearest?


[charconv.to.chars] says the following:

The functions that take a floating-point value but not a precision parameter ensure that the string representation consists of the smallest number of characters such that there is at least one digit before the radix point (if present) and parsing the representation using the corresponding from_chars function recovers value exactly.

If there are several such representations, the representation with the smallest difference from the floating-point argument value is chosen, resolving any remaining ties using rounding according to round_to_nearest ([round.style]).

I don't understand when the very last disambiguation (using round_to_nearest) would actually happen. Presumably, this breaks an exact tie when the last nonzero digit in in a number is 5, and that digit is not necessary to represent the same value. For example, hypothetically speaking:

These examples are hypothetical, but they show when the round_to_nearest disambiguation is necessary. Does there exist any real example of where it applies? In other words, does there exist a floating-point number whose exact decimal value has a least significant digit of 5, and only that digit is insignificant?


Note: I don't think the first bullet can ever apply to hex floats because you simply need to represent every quartet of mantissa bits using a hex digit, and drop trailing zeros. Rounding never actually happens; there are no insignificant digits (except trailing zeros), and there is nothing to disambiguate.


Solution

  • An example is the single-precision value 2097152.25. The shortest round-trip representations are 2097152.2 and 2097152.3. The former is chosen because 2 is even.

    In general, I think if a floating-point type has N mantissa bits (including the implicit bit), for any integer a in [2N - 4, 2N - 2), a + 0.25 and a + 0.75 will use the disambiguation.