This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++17 status.
stof() should callstrtof() andwcstof()Section: 27.4.5[string.conversions]Status:C++17Submitter: Stephan T. LavavejOpened: 2014-06-14Last modified: 2017-07-30
Priority:2
View all otherissues in [string.conversions].
View all issues withC++17 status.
Discussion:
stof() is currently specified to callstrtod()/wcstod() (which converts the given string todouble) and then it's specified to convert thatdouble tofloat. 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 forfloat anddouble, 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 convertX todouble, 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 convertY tofloat, 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.