, 1 min read
Rounding modes: std::from_chars versus strtod/strtof
A recent C++ standard (C++17) introduced new functions to parse floating-point numbers std::from_chars, from strings (e.g., ASCII text) to binary numbers. How should such a function parse values that cannot be represented exactly? The specification states that the resulting value rounded to nearest. This means that 1.0000000000000000001 and 0.999999999999999999 become exactly 1.0.
The C language has its own functions (strtod/strtof). I could not find a reference in the standard as to how it should round, but the source code suggests that the functions round according to the current floating-point rounding mode, as determined by the fegetround() function. One can round toward zero, up, down or to nearest. I wrote a small command-line utility to test it out. And indeed, I get the following results under LLVM and GCC:
string | UPWARD | DOWNWARD | TONEAREST |
---|---|---|---|
1.0000000000000000001 | 1.00001 | 1.0 | 1.0 |
0.999999999999999999 | 1.0 | 0.999999 | 0.999999 |
Thus you cannot assume that, in general, std::from_chars will agree with strtod/strtof even for just boring strings such as 0.999999999999999999.
Thankfully, you can check the rounding mode efficiently.