Escolar Documentos
Profissional Documentos
Cultura Documentos
#IND, etc
Pgina 1 de 5
Dividing a positive number by zero produces a positive infinity and dividing a negative number by zero produces a negative infinity. Example code at the end of this page will demonstrate some operations that produce infinities. Some operations don't make mathematical sense, such as taking the square root of a negative number. (Yes, this operation makes sense in the context of complex numbers, but a double represents a real number and so there is no double to represent the result.) The same is true for logarithms of negative numbers. Both sqrt(-1.0) and log(-1.0) would return a NaN, the generic term for a "number" that is "not a number". Windows displays a NaN as -1.#IND ("IND" for "indeterminate") while Linux displays nan. Other operations that would return a NaN include 0/0, 0*, and /. See the sample code below for examples. In short, if you get 1.#INF or inf, look for overflow or division by zero. If you get 1.#IND or
nan, look for illegal operations. Maybe you simply have a bug. If it's more subtle and you have
something that is difficult to compute, see Avoiding Overflow, Underflow, and Loss of Precision. That article gives tricks for computing results that have intermediate steps overflow if computed directly.
http://www.johndcook.com/IEEE_exceptions_in_cpp.html
20/10/2011
Pgina 2 de 5
Ordinary numbers always equal themselves, but NaNs do not. I've used this trick on Windows, Linux, and Mac OSX. If you ever use this trick, put big bold comments around your code so that some well-meaning person won't come behind you and delete what he or she things is useless code. Better yet, put the test in a well-documented function in a library that has controlled access. The following function will test whether x is a (possibly infinite) number.
bool IsNumber(double x) { // This looks like it should always be true, // but it's false if x is a NaN. return (x == x); }
To test whether a variable contains a finite number, (i.e. not a NaN and not an infinity) you can use code like the following.
Here DBL_MAX is a constant defined in float.h as the largest double that can be represented. Comparisons with NaNs always fail, even when comparing to themselves, and so the test above will fail for a NaN. If x is not a NaN but is infinite, one of the two tests will fail depending on whether it is a positive infinity or negative infinity.
_FPCLASS_SNAN _FPCLASS_QNAN _FPCLASS_NINF _FPCLASS_NN _FPCLASS_ND _FPCLASS_NZ _FPCLASS_PZ _FPCLASS_PD _FPCLASS_PN _FPCLASS_PINF
// // // // // // // // // //
signaling NaN quiet NaN negative infinity negative normal negative denormal -0 +0 positive denormal positive normal positive infinity
The following code illustrates which kinds of operations result in which kinds of numbers. To port this code to Linux, the FPClass function would need to use fp_class_d and its corresponding constants.
http://www.johndcook.com/IEEE_exceptions_in_cpp.html
20/10/2011
Pgina 3 de 5
using namespace std; string FPClass(double x) { int i = _fpclass(x); string s; switch (i) { case _FPCLASS_SNAN: s case _FPCLASS_QNAN: s case _FPCLASS_NINF: s case _FPCLASS_NN: s case _FPCLASS_ND: s case _FPCLASS_NZ: s case _FPCLASS_PZ: s case _FPCLASS_PD: s case _FPCLASS_PN: s case _FPCLASS_PINF: s } return s; }
= = = = = = = = = =
"Signaling NaN"; "Quiet NaN"; "Negative infinity (-INF)"; "Negative normalized non-zero"; "Negative denormalized"; "Negative zero (-0)"; "Positive 0 (+0)"; "Positive denormalized"; "Positive normalized non-zero"; "Positive infinity (+INF)";
break; break; break; break; break; break; break; break; break; break;
string HexDump(double x) { unsigned long* pu; pu = (unsigned long*)&x; ostringstream os; os << hex << pu[0] << " " << pu[1]; return os.str(); } // ---------------------------------------------------------------------------int main() { double x, y, z; cout << "Testing z = 1/0\n"; // cannot set x = 1/0 directly or would produce compile error. x = 1.0; y = 0; z = x/y; cout << "z = " << x/y << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting z = -1/0\n"; x = -1.0; y = 0; z = x/y; cout << "z = " << x/y << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting z = sqrt(-1)\n"; x = -1.0; z = sqrt(x); cout << "z = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n";
http://www.johndcook.com/IEEE_exceptions_in_cpp.html
20/10/2011
Pgina 4 de 5
cout << "\nTesting z = log(-1)\n"; x = -1.0; z = sqrt(x); cout << "z = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting overflow\n"; z = DBL_MAX; cout << "z = DBL_MAX = " << z; z *= 2.0; cout << "; 2z = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting denormalized underflow\n"; z = DBL_MIN; cout << "z = DBL_MIN = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; z /= pow(2.0, 52); cout << "z = DBL_MIN / 2^52= " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; z /= 2; cout << "z = DBL_MIN / 2^53= " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting z = +infinity + -infinty\n"; x = 1.0; y = 0.0; x /= y; y = -x; cout << x << " + " << y << " = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting z = 0 * infinity\n"; x = 1.0; y = 0.0; x /= y; z = 0.0*x; cout << "x = " << x << "; z = 0*x = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting 0/0\n"; x = 0.0; y = 0.0; z = x/y; cout << "z = 0/0 = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting z = infinity/infinity\n"; x = 1.0; y = 0.0; x /= y; y = x; z = x/y; cout << "x = " << x << "; z = x/x = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting x fmod 0\n"; x = 1.0; y = 0.0; z = fmod(x, y); cout << "fmod(" << x << ", " << y << ") = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nTesting infinity fmod x\n"; y = 1.0; x = 0.0; y /= x; z = fmod(y, x); cout << "fmod(" << y << ", " << x << ") = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; cout << "\nGetting cout to print QNAN\n"; unsigned long nan[2]={0xffffffff, 0x7fffffff};
http://www.johndcook.com/IEEE_exceptions_in_cpp.html
20/10/2011
Pgina 5 de 5
z = *( double* )nan; cout << "z = " << z << "\n"; cout << HexDump(z) << " _fpclass(z) = " << FPClass(z) << "\n"; return 0; }
To learn more
For a brief explanation of numerical limits and how floating point numbers are laid out in memory, see Anatomy of a floating point number. For much more detail regarding exceptions and IEEE arithmetic in general, see What every computer scientist should know about floating-point arithmetic.
Home
Blog
Contact jdc
http://www.johndcook.com/IEEE_exceptions_in_cpp.html
20/10/2011