1

真的很奇怪:

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。操作系统 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:当我/fp:strict在 C++/代码生成中设置开关时,结果与 Debug+Win32 相同,但使用 Release+Win32 时,c = a * b; // NaN无论c = (1/sigma) * exp(-1/sigma); // 0是否尝试,它都会更改为。我不明白为什么它保留NaN+NaN在 Debug+Win32 并且没有之前的尝试。当结果与 Release 不同时,如何调试必须是浮点安全的程序/fp:strict取决于先前的尝试?

编辑 3:这里有一个完整的程序:

// On VC++ 2010 Express in default Win32-Debug mode for empty console application.
// OS: Windows 7 Pro 64-Bit, CPU: Intel Core i5.
// Even when /fp:strict is set, same behaviour.
//
// Win32-Release mode: first c == 0, second c == NaN (independent of try)
// with /fp:strict: first c == NaN, second c == 0 (also independent of try)

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    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 with preceding try or
    cout << c << endl;              // NaN without preceding try

    cin.get();
    return 0;
}
4

1 回答 1

2

由于寄存器分配/使用的差异,可能会发生这类事情。例如 - 使用 try-catch 块,值sigma可能被保存为 64 位double,然后从内存中重新加载,而没有该块,它可能使用更高精度的 80 位寄存器(参见http://en. wikipedia.org/wiki/Extended_precision)不四舍五入到 64 位。如果你在乎的话,我建议你检查你的组件。

于 2013-11-19T10:04:48.747 回答