std::strod()
converts string to double. But in one particular case, there is a tiny decimal error. This error can also be seen with atof()
and sscanf()
. The error only occurs if all the following conditions are met:
- Visual Studio 2015 (or VS 2015 update 1)
- Build for 64 bit (x64)
- Call to
_controlfp_s()
to set "rounding towards minus infinity" - The number has a decimal part, e.g. 0.5 or 2.5 (not an integer)
(I have only tested on 64 bit Windows 8.1 Enterprise) A simple example is here:
#include <string>
inline double fromString(const std::string& s) {
size_t idx;
return std::stod(s, &idx);
}
int main()
{
double res1 = fromString("0.5");
unsigned tmp;
_controlfp_s(&tmp, RC_DOWN, MCW_RC);
double res2 = fromString("0.5");
_controlfp_s(&tmp, RC_NEAR, MCW_RC);
double res3 = fromString("0.5");
}
std::stod()
is calling std::calling strtod()
in stdlib.h.
res1
will be exactly 0.5, but res2
will be 0.50000000000000011
_controlfp_s(&tmp, RC_DOWN, MCW_RC);
controls rounding errors, in this case it is set to round towards minus infinity.
If it is set back to default with _controlfp_s(&tmp, RC_NEAR, MCW_RC);
then strod()
is exact again, so res3
is 0.5
Note that some decimal numbers cannot be represented exactly. But some numbers can, e.g. 2.5, 0.5, and 0.375, but they all get a rounding error in the above example.
Weird, isn't it?
Am I doing something wrong, or is this a bug in Visual Studio's standard library?