std::strod()
将字符串转换为双精度。但在一种特殊情况下,存在一个微小的小数错误。atof()
使用和也可以看到此错误sscanf()
。仅当满足以下所有条件时才会发生错误:
- Visual Studio 2015(或 VS 2015 更新 1)
- 为 64 位 (x64) 构建
- 调用以
_controlfp_s()
设置“向负无穷舍入” - 数字有小数部分,例如 0.5 或 2.5(不是整数)
(我只在 64 位 Windows 8.1 Enterprise 上测试过)这里有一个简单的例子:
#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()
正在调用std::calling strtod()
stdlib.h。
res1
正好是 0.5,但res2
会是 0.50000000000000011
_controlfp_s(&tmp, RC_DOWN, MCW_RC);
控制舍入误差,在这种情况下,它设置为向负无穷大舍入。如果将其设置回默认值,_controlfp_s(&tmp, RC_NEAR, MCW_RC);
则 thenstrod()
再次精确,res3
0.5也是如此
请注意,某些十进制数无法精确表示。但有些数字可以,例如 2.5、0.5 和 0.375,但在上面的示例中它们都会出现舍入误差。
很奇怪,不是吗?
我做错了什么,还是这是 Visual Studio 标准库中的错误?