This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.
stof() should call strtof() and wcstof()Section: 27.4.5 [string.conversions] Status: C++17 Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2017-07-30
Priority: 2
View all other issues in [string.conversions].
View all issues with C++17 status.
Discussion:
stof() is currently specified to call strtod()/wcstod() (which converts the given string to
double) and then it's specified to convert that double to float. This performs rounding twice,
which introduces error. Here's an example written up by James McNellis:
X:
1.999999821186065729339276231257827021181583404541015625 (X)
This number is exactly representable in binary as:
1.111111111111111111111101000000000000000000000000000001 * ^1st ^23rd ^52nd
I've marked the 23rd and 52nd fractional bits. These are the least significant bits for float and double,
respectively.
float, we take the 23 most significant bits:
1.11111111111111111111110
The next bit is a one and the tail is nonzero (the 54th fractional bit is a one), so we round up. This gives us the correctly rounded result:
1.11111111111111111111111
So far so good. But... If we convert X to double, we take the 52 most significant bits:
1.1111111111111111111111010000000000000000000000000000 (Y)
The next bit is a zero, so we round down (truncating the value). If we then convert Y to float, we take
its 23 most significant bits:
1.11111111111111111111110
The next bit is a one and the tail is zero, so we round to even (leaving the value unchanged). This is off by 1ulp from the correctly rounded result.
[2014-06 Rapperswil]
Marshall Clow will look at this.
[Urbana 2014-11-07: Move to Ready]
Proposed resolution:
This wording is relative to N3936.
Change 27.4.5 [string.conversions] p4+p6 as indicated:
float stof(const string& str, size_t* idx = 0); double stod(const string& str, size_t* idx = 0); long double stold(const string& str, size_t* idx = 0);-4- Effects:
[…] -6- Throws:the first twoThese functions callstrtof(str.c_str(), ptr),strtod(str.c_str(), ptr), andthe third function callsstrtold(str.c_str(), ptr), respectively. Each function returns the converted result, if any. […]invalid_argumentifstrtof,strtod, orstrtoldreports that no conversion could be performed. Throwsout_of_rangeifstrtof,strtod, orstrtoldsetserrnotoERANGEor if the converted value is outside the range of representable values for the return type.
Change 27.4.5 [string.conversions] p11+p13 as indicated:
float stof(const wstring& str, size_t* idx = 0); double stod(const wstring& str, size_t* idx = 0); long double stold(const wstring& str, size_t* idx = 0);-11- Effects:
[…] -13- Throws:the first twoThese functions callwcstof(str.c_str(), ptr),wcstod(str.c_str(), ptr), andthe third function callswcstold(str.c_str(), ptr), respectively. Each function returns the converted result, if any. […]invalid_argumentifwcstof,wcstod, orwcstoldreports that no conversion could be performed. Throwsout_of_rangeifwcstof,wcstod, orwcstoldsetserrnotoERANGE.