使用C ++实现VS6和VS2008之间的数值精度差异?

时间:2010-07-28 15:01:35

标签: c++ visual-studio visual-studio-2008

我一直致力于将遗留项目从Visual Studio 6迁移到2008年。在跳过几个障碍后,我现在已经建立并执行了新项目。但是,我注意到程序的两个版本的输出略有不同,好像浮点计算不相等,尽管代码是相同的。

这些差异通常开始很小(<1.0E-6),但在许多计算中累积到它们开始对输出产生实质性影响的程度。作为一个例子,我在计算的第一步之后看了一个关键变量的内存中的精确双精度存储并看到了:

Visual Studio 6表示: 0x4197D6CC85AC68D9
十进制等效: 99988257.4183687120676040649414

Visual Studio 2008表示: 0x4197D6CC85AC68EB
十进制等效: 99988257.4183689802885055541992

我试图对此进行调试以追踪差异开始的位置,但输出来自迭代数值求解器,因此以如此高的精度来追踪这一过程将是一个耗时的过程。 / p>

是否有人知道编译器的两个版本的双精度算术运算之间存在任何预期的差异? (或者关于可能导致这种情况的任何其他想法?)

现在我的下一步可能是尝试创建一个简单的演示应用程序来显示问题,并且可以更容易地进行检查。

谢谢!

2 个答案:

答案 0 :(得分:4)

这只是猜测,但大多数现代Intel / AMD CPU都有两个独立的FPU型号:旧式i386 FPU和较新的基于SSE / SSE2的型号。后者具有更灵活的编程模型,通常是首选。

如果VS6和VS2008都为同一型号生成代码,则应检查,因为旧式FPU具有80位中间结果,这可能导致更少的舍入和可能更好的结果,但实际结果取决于优化器呢。这是科学界人士真正讨厌的东西。例如,如果操作数溢出到内存中,那么它们会被截断为64位,并且会丢失额外的精度。

IIRC然后VS6无法生成SSE / SSE2代码,但它有一个/ fp:exact选项将所有中间结果舍入到其声明的大小。我想,VS 2008也有这面旗帜。所以我建议您尝试/ fp:两个编译器的精确度并再次比较结果。

答案 1 :(得分:0)

正如您所注意到的,浮点结果会留下很多不一致的空间。你确定新版本不太正确吗?您对可以执行的结果有任何健全性检查吗?

首先,您的算法似乎对输入的微小变化有些敏感。您是否检查过您的代码(特别是加法和减法)以确保没有机会引入错误?

至少在x86上,大多数FP操作都是在80位内部寄存器中完成的,但内存中只有64位。如果两个不同的编译器将中间结果复制到内存(并截断)不同的点,那肯定会导致不同的答案。编译器优化逻辑肯定会导致它的行为不同,特别是如果较新的编译器利用了旧的编译器没有的额外寄存器。

有一次,我知道有一个“使用一致浮点”选项,但我不记得它在哪个版本。这导致值在每次操作后被截断为64位,但确保结果在多次运行中都是一致的。