gpt4 book ai didi

c++ - std::strtod() 中的十进制错误与 Visual Studio 2015,64 位

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:48:14 26 4
gpt4 key购买 nike

std::strod() 将字符串转换为 double 。但在一种特殊情况下,存在微小的小数错误。使用 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() 在 stdlib.h 中调用 std::calling strtod()res1 将正好是 0.5,但 res2 将是 0.50000000000000011

_controlfp_s(&tmp, RC_DOWN, MCW_RC); 控制舍入误差,在本例中它被设置为向负无穷大舍入。如果使用 _controlfp_s(&tmp, RC_NEAR, MCW_RC); 将其设置回默认值,则 strod() 再次准确,因此 res3 为 0.5

请注意,有些十进制数字无法准确表示。但是有些数字可以,例如2.5、0.5 和 0.375,但在上例中它们都出现舍入误差。

很奇怪,不是吗?

我做错了什么,还是 Visual Studio 标准库中的错误?

最佳答案

感谢 Adrian McCarthy 提供的链接,我找到了解决方法:使用fesetround() 而不是 _controlfp_s():

#if _MSC_VER == 1900
//Visual Studio 2015
fesetround(FE_DOWNWARD);
#else
_controlfp_s(&tmp, RC_DOWN, MCW_RC);
#endif

fesetround() 是在 VS2015 中引入的。我会将错误报告给 Microsoft。还可以使用 #if _MSC_VER == 1900 && defined(_WIN64) 来更精确,因为 32 位目标不存在错误。

关于c++ - std::strtod() 中的十进制错误与 Visual Studio 2015,64 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34141113/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com