本当に奇妙です:
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;
いくつかの最適化により、2 番目の c の結果が 0 になる可能性があります。
BUT : try/catch ブロックを削除すると、2 番目の c は NaN のままです! なぜこの異なる動作??? 私のコンパイラは VC++ 2010 Express です。OS Windows7 64ビット。iostream や cmath などの標準ライブラリのみを使用します。
編集:私の最初の観察は、空のコンソールアプリケーションのDebug + Win32デフォルト設定でした。Release+Win32 では、結果は次のとおりです。最初の c 0、2 番目の 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 では、try の有無に関係なく、c = a * b; // NaN
に変わります。Debug+Win32 のc = (1/sigma) * exp(-1/sigma); // 0
ままで、先行試行がない理由がわかりません。前の試行に応じてNaN+NaN
結果がリリースと異なる場合、浮動小数点セーフでなければならないプログラムをデバッグする方法は?/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;
}