CString.Format 以相同的精度产生不同的值

Yau*_*n.F 6 c++ string floating-point mfc atl

抱歉,这个问题可能很愚蠢,因为我是 C# 开发人员,所以我很难找到一些想法。

我们正在从 VC++ 2013 迁移到 VC++ 2019。我们有 2 个安装了 VC++2013 和 VC++2019 的类似 VM。项目已经在使用 VC++2019。在 2 个 VM 上运行时,简单评估的结果不同:

CString Value;
int precision = 8;
double number = 50.634765625;
String^ RetValue;

Value.Format(_T("%.*f"), precision, number);
RetValue = gcnew String(Value.GetString());
Run Code Online (Sandbox Code Playgroud)

在一个VM(Win 7 64位)上,我们在另一台VM(win10 64位)上有RetValue“50.63476563” - “50.63476562”我期望的所有工具都是相同的(很难说100%,因为安装了很多,但最重要的是c ++是)。

在 VS2013 下转换和运行项目时,两个 VM 上的结果相同 - “50.63476563”。

是否有任何控制格式的选项设置?或者为什么选择一个 VM 截断来支持舍入?

UPDATE 所以这个问题真的与VS2013/VS2019的差异有关。我发现了为什么我们在使用相同 VS2019 的 2 个虚拟机上有不同的结果。所以:

  1. VS2013 四舍五入 50.634765625 == VS 2019 版本四舍五入
  2. VS2013 四舍五入 50.634765625 != VS 2019 调试四舍五入

在这两种情况下,四舍五入方向都是最接近的。所以 MSFT 在发布/调试中以不同的方式解释最接近。C++ 编译器选项使 /MD 与 /MDd 有所不同。

除了切换到 /MD 以强制舍入对整个项目在调试中采用旧方法外,找不到任何其他方法。

Jos*_*son 6

我们在测试中发现 2013 年和 2017 年之间存在差异。我们看到将数字 .249500 渲染为三位数的差异。2013 = 0.250 而 2017 = 0.249。考虑这个例子:

#include <stdio.h>

// little endian bytes, to avoid parsing differences between both compilers
unsigned char bytesOfDouble[] = {0x56, 0x0E, 0x2D, 0xB2, 0x9D, 0xEF, 0xCF, 0x3F}; 
double& dVal = reinterpret_cast<double&>(bytesOfDouble);

void PrintDouble(const double& d)
{
    printf("printf (%%.3f): %.3f\n", d);
    printf("printf (%%.3g): %.3g\n", d);

    printf("printf (%%f)  : %f\n", d);
    printf("printf (%%g)  : %g\n", d);
}

int main(int argc, char** argv)
{
    PrintDouble(dVal);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果用VS2013和VS2017编译,会得到不同的结果。如果你尝试 g++ 或 clang,你会得到与 VS2017 相同的结果。

如何在两者之间获得相同的结果?IDK...我认为 MS 肯定改变了他们的底层 C 运行时。

  • VS 2013 是在切换到 UCRT 之后的 VS 2017 之前,因此[浮点迁移问题](https://docs.microsoft.com/en-us/cpp/porting/floating-point-migration-issues?view= vs-2019)可能相关(抄送@Yauhen.F)。 (3认同)