Errors during floating point operation operations are often ignored neglected by the applications; instead much the greatest effort is only usually in validating the operands before an operation. Errors occurring during floating point operations are admittedly difficult to determine and diagnose, but the benefits of understanding how to check for these errors and employing the process of doing so may outweigh the costs. This recommendation suggests ways to capture errors during floating point operations.
Consider the following code: What makes it difficult to detect these errors is that the application will not abort or even complain when they occur. For example, the following statement generates a runtime error or exception.
Code Block |
---|
int j = 0; int iResult = 1 / j; |
This one, however, generates no error messagesRunning the code above results in undefined behavior. On most implementations, integer division by zero is a terminal error, commonly printing a diagnostic message and aborting the program.
Code Block |
---|
double x = 0.0; double dResult = 1 / x; |
Though the code above also results in undefined behavior, most implementations do not view floating point division by zero as a terminal error. If extra steps are not taken the operation happens "silently."
Wiki Markup |
---|
Though floating point exception conditions and handling are standardized by \[[IEEE 754|AA. C References#IEEE 754 2006]\], operating systems implement support for handling floating point errors and other conditions in different ways. |
The most portable way of determining a floating point exceptional condition has occurred is to make use of the floating point exception faculties provided by C99 in {{fenv.h}} \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\]. |
A less portable, but sometimes more intuitive and/or informative, solution is to make use of the faculties provided by the underlying implementation. If this approach is taken, the caveats of that system need to be well understood. The following table can serve as a starting point for some common architectures:
Operating System | How to handle floating point | Operating System | Handling FP errors | |
---|---|---|---|---|
Linux | C99 FP functions - These functions are declared in | AA. C References#Open Group 04]] | Use the C99 floating point exception functions. | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f1f5f82a0298a44b-92c1a2fb-4efd411e-964fbdd6-fd6eb6899c0dfae73c51067f"><ac:plain-text-body><![CDATA[ | Windows | Structured Exception Handling - user defined handler Either use the C99 floating point exception function or structured exception handling through | AA. C References#MSDN]] | ]]></ac:plain-text-body></ac:structured-macro> |
Non-Compliant Code Example
In this NCCEthe following non-compliant code, floating point operations are carried out and there is no observation for errors during floating point operations. Please note that the range check on various operands for the operations has been intentionally ignored because we intend to capture the errors during a floating point operation.
Code Block | ||
---|---|---|
| ||
fpOper_noErrorChecking(void) { /* ... */ double a = 1e-40, b, c = 0.1; float x = 0, y; /* inexact and underflows */ y = a; /* divide by zero operation */ b = y / x; /* inexact (loss of precision) */ c = sin(30) * a; /* ... */ } |
However, as the comments indicate, various exceptional conditions occur, that may lead to unexpected arithmetic results.
Compliant Solution 1
This compliant solution uses C99 standard functions to handle floating point errors.
...