我正在使用Visual Studio 2008并遇到过这样一种情况,即同一类库的两个不同版本中的相同代码显然会产生不同的答案。
以下代码反映了我重现问题的尝试。它只需要两对数字(cx,cy)和(rx,ry),减去它们,并以十进制和十六进制格式显示结果(tx,ty)。
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
string dhex(double x) { // double to hex
union {
unsigned long long n;
double d;
} value;
value.d = x;
std::ostringstream buf;
buf << "0x" << std::hex << std::setfill('0') << std::setw(16) << value.n;
return buf.str();
}
double i64tod(unsigned long long n) { // hex to double
double *DP = (double *) &n;
return *DP;
}
int main(int argc, char **argv) {
double tx, ty, cx, cy, rx, ry;
cx = i64tod(0x3fb63f141205bc02); cy = i64tod(0x40019eb851eb851f);
rx = i64tod(0x3fa222fa84a5161c); ry = i64tod(0x40011f8441720667);
tx = cx - rx;
ty = cy - ry;
cout << setprecision(22);
cout << " cx = " << setw(22) << cx << ", cy = " << setw(22) << cy
<< " (" << dhex(cx) << ", " << dhex(cy) << ")" << endl;
cout << " rx = " << setw(22) << rx << ", ry = " << setw(22) << ry
<< " (" << dhex(rx) << ", " << dhex(ry) << ")" << endl;
cout << " tx = " << setw(22) << tx << ", ty = " << setw(22) << ty
<< " (" << dhex(tx) << ", " << dhex(ty) << ")" << endl;
return 0;
}
此代码的输出为:
cx = 0.086900000000000005, cy = 2.2025000000000001 (0x3fb63f141205bc02, 0x40019eb851eb851f)
rx = 0.035423115436554492, ry = 2.1403889763758346 (0x3fa222fa84a5161c, 0x40011f8441720667)
tx = 0.051476884563445513, ty = 0.06211102362416554 (0x3faa5b2d9f6661e8, 0x3fafcd041e5fae00)
有问题的应用程序有一个类库,它是一个“池引擎”,即。它模拟了水池/斯诺克投篮的物理特性。
最近对该库进行的一系列更改导致验证测试失败,其中涉及应生成特定表状态的特定镜头序列。
我将其追踪到那个简单的减法操作。当新版本执行减法时,它会产生:
cx = 0.086900000000000005, cy = 2.2025000000000001 (0x3fb63f141205bc02, 0x40019eb851eb851f)
rx = 0.035423115436554492, ry = 2.1403889763758346 (0x3fa222fa84a5161c, 0x40011f8441720667)
tx = 0.051476884563445513, ty = ?0.062111023624165547 (0x3faa5b2d9f6661e8, 0x3fafcd041e5fae01)
正如你所看到的,区别在于最低位(ty),但有时甚至更多。这是另一对点值的结果:
cx = 1.0641, cy = -0.0545 (0x3ff1068db8bac711, 0xbfabe76c8b439581)
rx = 1.0878512271746064, ry = 0.022594280641953058 (0x3ff167d6b03a0dee, 0x3f9722f481bc3f0d)
tx = -0.023751227174606315, ty = -0.077094280641953061 (0xbf98523ddfd1b740, 0xbfb3bc736610da84)
上面的程序和较旧的库版本也同意这个案例,但在这种情况下,新的库版本给出了不同的答案(对于tx):
tx = -0.023751227174606343, ty = -0.077094280641953061 (0xbf98523ddfd1b748, 0xbfb3bc736610da84)
这两个版本的库都有相同的编译器选项,并且所讨论的函数(碰撞处理程序)没有被更改所改变(我只是通过替换没有带结构的方法的类来简化库)。
我应该补充一点,当新版本获得不同的结果时,至少它是一致的,即。它总是会产生不同的答案。
我可以简单地接受新版本并将验证测试替换为匹配的版本,但我真的想知道为什么会发生这种情况。
为了记录,我试图通过改变编译器选项等来获得上面的独立程序以提供“替代”答案,但没有运气。它只能在新的库版本中原位失败。