The IEEE 754 standard defines five exceptions that can occur during a calculation. Each corresponds to a particular sort of error, such as overflow.
When exceptions occur (when exceptions are raised, in the language of the standard), one of two things can happen. By default the exception is simply noted in the floating-point status word, and the program continues as if nothing had happened. The operation produces a default value, which depends on the exception (see the table below). Your program can check the status word to find out which exceptions happened.
Alternatively, you can enable traps for exceptions. In that case, when an exception is raised, your program will receive the SIGFPE signal. The default action for this signal is to terminate the program. Chapter 25, for how you can change the effect of the signal.
In the System V math library, the user-defined function matherr is called when certain exceptions occur inside math library functions. However, the Unix98 standard deprecates this interface. We support it for historical compatibility, but recommend that you do not use it in new programs.
The exceptions defined in IEEE 754 are:
This exception is raised if the given operands are invalid for the operation to be performed. Examples are (see IEEE 754, section 7):
Addition or subtraction: oo - oo. (But oo + oo = oo).
Multiplication: 0 * oo.
Division: 0/0 or oo/oo.
Remainder: x REM y, where y is zero or x is infinite.
Square root if the operand is less then zero. More generally, any mathematical function evaluated outside its domain produces this exception.
Conversion of a floating-point number to an integer or decimal string, when the number cannot be represented in the target format (due to overflow, infinity, or NaN).
Conversion of an unrecognizable input string.
Comparison via predicates involving or , when one or other of the operands is NaN. You can prevent this exception by using the unordered comparison functions instead; see the section called “Floating-Point Comparison Functions”.
If the exception does not trap, the result of the operation is NaN.
This exception is raised when a finite nonzero number is divided by zero. If no trap occurs the result is either +oo or -oo, depending on the signs of the operands.
This exception is raised whenever the result cannot be represented as a finite value in the precision format of the destination. If no trap occurs the result depends on the sign of the intermediate result and the current rounding mode (IEEE 754, section 7.3):
Round to nearest carries all overflows to oo with the sign of the intermediate result.
Round toward 0 carries all overflows to the largest representable finite number with the sign of the intermediate result.
Round toward -oo carries positive overflows to the largest representable finite number and negative overflows to -oo.
Round toward oo carries negative overflows to the most negative representable finite number and positive overflows to oo.
Whenever the overflow exception is raised, the inexact exception is also raised.
The underflow exception is raised when an intermediate result is too small to be calculated accurately, or if the operation's result rounded to the destination precision is too small to be normalized.
When no trap is installed for the underflow exception, underflow is signaled (via the underflow flag) only when both tininess and loss of accuracy have been detected. If no trap handler is installed the operation continues with an imprecise small value, or zero if the destination precision cannot hold the small exact result.
This exception is signalled if a rounded result is not exact (such as when calculating the square root of two) or a result overflows without an overflow trap.
IEEE 754 floating point numbers can represent positive or negative infinity, and NaN (not a number). These three values arise from calculations whose result is undefined or cannot be represented accurately. You can also deliberately set a floating-point variable to any of them, which is sometimes useful. Some examples of calculations that produce infinity or NaN:
1/0 = oo log (0) = -oo sqrt (-1) = NaN
When a calculation produces any of these values, an exception also occurs; see the section called “FP Exceptions”.
The basic operations and math functions all accept infinity and NaN and produce sensible output. Infinities propagate through calculations as one would expect: for example, 2 + oo = oo, 4/oo = 0, atan (oo) = pi/2. NaN, on the other hand, infects any calculation that involves it. Unless the calculation would produce the same result no matter what real value replaced NaN, the result is NaN.
In comparison operations, positive infinity is larger than all values except itself and NaN, and negative infinity is smaller than all values except itself and NaN. NaN is unordered: it is not equal to, greater than, or less than anything, including itself. x == x is false if the value of x is NaN. You can use this to test whether a value is NaN or not, but the recommended way to test for NaN is with the isnan function (the section called “Floating-Point Number Classification Functions”). In addition, , , =, and = will raise an exception when applied to NaNs.
math.h defines macros that allow you to explicitly set a variable to infinity or NaN.
float function>INFINITY/function> An expression representing positive infinity. It is equal to the value produced by mathematical operations like 1.0 / 0.0. -INFINITY represents negative infinity.
You can test whether a floating-point value is infinite by comparing it to this macro. However, this is not recommended; you should use the isfinite macro instead. the section called “Floating-Point Number Classification Functions”.
This macro was introduced in the ISO C99 standard.
float function>NAN/function> An expression representing a value which is "not a number". This macro is a GNU extension, available only on machines that support the "not a number" value--that is to say, on all machines that support IEEE floating point.
You can use #ifdef NAN to test whether the machine supports NaN. (Of course, you must arrange for GNU extensions to be visible, such as by defining _GNU_SOURCE, and then you must include math.h.)
IEEE 754 also allows for another unusual value: negative zero. This value is produced when you divide a positive number by negative infinity, or when a negative result is smaller than the limits of representation. Negative zero behaves identically to zero in all calculations, unless you explicitly test the sign bit with signbit or copysign.
ISO C99 defines functions to query and manipulate the floating-point status word. You can use these functions to check for untrapped exceptions when it's convenient, rather than worrying about them in the middle of a calculation.
These constants represent the various IEEE 754 exceptions. Not all FPUs report all the different exceptions. Each constant is defined if and only if the FPU you are compiling for supports that exception, so you can test for FPU support with #ifdef. They are defined in fenv.h.
The inexact exception.
The divide by zero exception.
The underflow exception.
The overflow exception.
The invalid exception.
The macro FE_ALL_EXCEPT is the bitwise OR of all exception macros which are supported by the FP implementation.
These functions allow you to clear exception flags, test for exceptions, and save and restore the set of exceptions flagged.
int function>feclearexcept/function> (int excepts) This function clears all of the supported exception flags indicated by excepts.
The function returns zero in case the operation was successful, a non-zero value otherwise.
int function>feraiseexcept/function> (int excepts) This function raises the supported exceptions indicated by excepts. If more than one exception bit in excepts is set the order in which the exceptions are raised is undefined except that overflow (FE_OVERFLOW) or underflow (FE_UNDERFLOW) are raised before inexact (FE_INEXACT). Whether for overflow or underflow the inexact exception is also raised is also implementation dependent.
The function returns zero in case the operation was successful, a non-zero value otherwise.
int function>fetestexcept/function> (int excepts) Test whether the exception flags indicated by the parameter except are currently set. If any of them are, a nonzero value is returned which specifies which exceptions are set. Otherwise the result is zero.
To understand these functions, imagine that the status word is an integer variable named status. feclearexcept is then equivalent to status = ~excepts and fetestexcept is equivalent to (status excepts). The actual implementation may be very different, of course.
Exception flags are only cleared when the program explicitly requests it, by calling feclearexcept. If you want to check for exceptions from a set of calculations, you should clear all the flags first. Here is a simple example of the way to use fetestexcept:
{ double f; int raised; feclearexcept (FE_ALL_EXCEPT); f = compute (); raised = fetestexcept (FE_OVERFLOW | FE_INVALID); if (raised FE_OVERFLOW) { /* ... */ } if (raised FE_INVALID) { /* ... */ } /* ... */ }
You cannot explicitly set bits in the status word. You can, however, save the entire status word and restore it later. This is done with the following functions:
int function>fegetexceptflag/function> (fexcept_t *flagp, int excepts) This function stores in the variable pointed to by flagp an implementation-defined value representing the current setting of the exception flags indicated by excepts.
The function returns zero in case the operation was successful, a non-zero value otherwise.
int function>fesetexceptflag/function> (const fexcept_t *flagp, int excepts) This function restores the flags for the exceptions indicated by excepts to the values stored in the variable pointed to by flagp.
The function returns zero in case the operation was successful, a non-zero value otherwise.
Note that the value stored in fexcept_t bears no resemblance to the bit mask returned by fetestexcept. The type may not even be an integer. Do not attempt to modify an fexcept_t variable.
Many of the math functions are defined only over a subset of the real or complex numbers. Even if they are mathematically defined, their result may be larger or smaller than the range representable by their return type. These are known as domain errors, overflows, and underflows, respectively. Math functions do several things when one of these errors occurs. In this manual we will refer to the complete response as signalling a domain error, overflow, or underflow.
When a math function suffers a domain error, it raises the invalid exception and returns NaN. It also sets errno to EDOM; this is for compatibility with old systems that do not support IEEE 754 exception handling. Likewise, when overflow occurs, math functions raise the overflow exception and return oo or -oo as appropriate. They also set errno to ERANGE. When underflow occurs, the underflow exception is raised, and zero (appropriately signed) is returned. errno may be set to ERANGE, but this is not guaranteed.
Some of the math functions are defined mathematically to result in a complex value over parts of their domains. The most familiar example of this is taking the square root of a negative number. The complex math functions, such as csqrt, will return the appropriate complex value in this case. The real-valued functions, such as sqrt, will signal a domain error.
Some older hardware does not support infinities. On that hardware, overflows instead return a particular very large number (usually the largest representable number). math.h defines macros you can use to test for overflow on both old and new hardware.
double function>HUGE_VAL/function> float function>HUGE_VALF/function> long double function>HUGE_VALL/function> An expression representing a particular very large number. On machines that use IEEE 754 floating point format, HUGE_VAL is infinity. On other machines, it's typically the largest positive number that can be represented.
Mathematical functions return the appropriately typed version of HUGE_VAL or −HUGE_VAL when the result is too large to be represented.