c++ - 浮点 NaN 取决于 C++ 中不相关的异常处理

标签 c++ exception floating-point nan extended-precision

真的很奇怪:

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 block 时,第二个 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:当我在 C++/codegeneration 中设置 /fp:strict 开关时,结果与 Debug+Win32 相同,但对于 Release+Win32 它发生了变化c = a * b;//NaNc = (1/sigma) * exp(-1/sigma);//0 无论是否尝试。我不明白为什么它在 Debug+Win32 下保持 NaN+NaN 并且之前没有尝试。尽管 /fp:strict 与 Release 的结果不同,但取决于前面的尝试,如何调试必须是浮点安全的程序?

编辑 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;
}

最佳答案

由于寄存器分配/使用的差异,可能会发生这些事情。例如 - 使用 try-catch block ,sigma 的值可能被保存为 64 位 double 然后从内存中重新加载,而没有它可能使用的 block 更高精度的 80 位寄存器(参见 http://en.wikipedia.org/wiki/Extended_precision),无需四舍五入为 64 位。如果您愿意,我建议您检查您的装配体。

关于c++ - 浮点 NaN 取决于 C++ 中不相关的异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20068186/

相关文章:

exception - 在Android中,无法处理从整洁架构中的用例抛出的异常

c# - 从 int 转换为 float 的问题

c# - 识别这些 "minimum" double 值并将其转换为 C# Double.MinValue 的最佳方法是什么?

c++ - 为什么动态绑定(bind)没有按预期运行?

c++ - std::vector<T> 是 `user-defined type` 吗?

c++ - Qt:如何使用 registerField() 在 QWizardPages 之间传递变量值

c++ - 在构造函数 C++ 中用零初始化二维数组

java - 如何在 Jetty 中记录异常堆栈跟踪?

c# - 如果我正在使用的 Web 服务超时,会抛出什么异常?

c++ - 为什么 c/c++ 浮点类型的命名如此奇怪?