Mathematical errors are a special kind of run-time error. They may
not necessarily cause your program to crash, but they are likely to
produce all sorts of strange results if you are doing some complex
calculations in your program. Consider the following line of code:
root = sqrt (-1.0);
Readers with a smattering of mathematics will recognise that this code
cannot give a sensible answer. The square root of -1 is a complex
number called i. The number i is a so-called imaginary
number, and cannot be represented by a floating-point value, which is
sqrt function returns.
What happens in such a case? Two things:
- The value returned is a special floating-point macro such as
NAN(which means "not a number") or
- More importantly from a debugging standpoint, a floating-point exception occurs. An exception is an error condition, and when a floating-point exception is raised, as the jargon goes, an error flag is set in the operating system, signifying what kind of exception it was (in other words, what kind of error caused the exception to be raised).
There are several kinds of floating-point exception:
FE_INVALID: The "Invalid Operation" exception. Raised if the operands are invalid for the given operation, for example, if you are trying to take the square root of a negative number, as above.
FE_DIVBYZERO: The "Division by Zero" exception. Raised when a finite, nonzero number is divided by zero.
FE_OVERFLOW: The "Overflow" exception. Raised when the result cannot be expressed as a finite value, for example when a finite, nonzero number is divided by zero. Whenever this exception is raised, the
FE_INEXACTexception is also raised.
FE_UNDERFLOW: The "Underflow" exception. Raised when an intermediate result is too small to be calculated accurately, or when an operation's rounded result is too small to be normalized. Normalisation, roughly speaking, is the process of converting a number to scientific notation, such as converting 235 to 2.35e2, where the mantissa, or number to the left of the
e, must not be zero. See Floating point variables, for more information on scientific notation.)
FE_INEXACT: The "Inexact" exception. Raised if a rounded result is not exact, for example when calculating an irrational number such as the square root of 2.
You can test for these exceptions with the
function, which takes one parameter, a bitwise OR'd list of the
exception flags from the list above for which you are testing, and
returns a nonzero value containing a bitwise OR'd list of the flags
you passed it for the exceptions that actually occurred. You can also
clear selected flags with the
feclearexcept function, which
accepts a bitwise-OR'd list of exception flags to clear, and returns
zero if it was successful. (You can pass either of these function the
FE_ALL_EXCEPT, which contains all of the floating-point
exception flags OR'd together.)
In case this explanation is unclear, let's look at a practical example.