真的很奇怪:
double *data; // uncorrelated
double a,b,c;
double sigma = 1e-309; // denormalized number
try { data = new double[10]; } // uncorrelated
catch(...) { cout << "error"; return 1; }
a = 1/sigma; // infinite
b = exp(-1/sigma); // 0
c = a * b; // NaN
cout << c << endl;
c = (1/sigma) * exp(-1/sigma); // 0
cout << c << endl;
好的,由于一些优化,第二个c结果可能是0。
但是:当我删除try / catch块时,第二个c仍然是NaN!为何这种不同的行为?我的编译器是VC ++ 2010 Express。 OS Windows 7 64位。我只使用像iostream和cmath这样的标准库。
编辑:我的第一个观察是针对空控制台应用程序的Debug + Win32默认设置。使用Release + Win32,结果是:第一个c 0,第二个c NaN - 无论是否存在try / catch!总结:
//Debug+Win32 // Release+Win32
//with try //without //with try //without
c = a * b; // NaN NaN 0 0
c = (1/sigma) * exp(-1/sigma); // 0 NaN NaN NaN
编辑2 :当我在C ++ / codegeneration中设置/fp:strict
开关时,结果与Debug + Win32相同,但使用Release + Win32时,它会更改为c = a * b; // NaN
和c = (1/sigma) * exp(-1/sigma); // 0
无论是否尝试。我不知道为什么它与Debug + Win32保持NaN+NaN
并没有先前的尝试。如果调试结果必须是浮点安全的,当结果与Release版本有所不同时,取决于前面的尝试?
编辑3 :这是一个完整的程序:
/fp:strict
答案 0 :(得分:2)
由于寄存器分配/使用的差异,可能会发生这些事情。例如 - 使用try-catch块,sigma
的值可能会被保存为64位double
,然后从内存重新加载,而没有块,它可能会使用更高精度的80-位寄存器(见http://en.wikipedia.org/wiki/Extended_precision)而不舍入为64位。如果你愿意,我建议你检查你的装配。