...
Operating System | How to handle floating point errors | |||
---|---|---|---|---|
Linux | Use the C99 floating-point exception functions. | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1e4394f87677473f-cd8f5a32-4ab142a1-b51f859f-60f00ac1509474fa5df7a327"><ac:plain-text-body><![CDATA[ | Windows | Either use the C99 floating-point exception function or structured exception handling through | AA. Bibliography#MSDN]] | ]]></ac:plain-text-body></ac:structured-macro> |
...
In this noncompliant code example, floating-point operations are performed without checking for errors. Note that range checking has been intentionally omitted because the intent is to detect errors following the floating-point operation.
Code Block | ||||
---|---|---|---|---|
| ||||
void 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; /* ... */ } |
...
This compliant solution uses C99 standard functions to handle floating-point errors.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <fenv.h> #pragma STDC FENV_ACCESS ON void fpOper_fenv(void) { double a = 1e-40, b, c = 0.1; float x = 0, y; int fpeRaised; /* ... */ feclearexcept(FE_ALL_EXCEPT); /* Store a into y is inexact and underflows: */ y = a; fpeRaised = fetestexcept(FE_ALL_EXCEPT); /* fpeRaised has FE_INEXACT and FE_UNDERFLOW */ feclearexcept(FE_ALL_EXCEPT); /* divide by zero operation */ b = y / x; fpeRaised = fetestexcept(FE_ALL_EXCEPT); /* fpeRaised has FE_DIVBYZERO */ feclearexcept(FE_ALL_EXCEPT); c = sin(30) * a; fpeRaised = fetestexcept(FE_ALL_EXCEPT); /* fpeRaised has FE_INEXACT */ feclearexcept(FE_ALL_EXCEPT); /* ... */ } |
...
Microsoft Visual Studio 2008 and earlier versions do not support C99 functions to handle floating-point errors. Windows provides an alternative method for handling floating-point errors using _statusfp()
, _statusfp2()
, and _clearfp()
.
Code Block | ||||
---|---|---|---|---|
| ||||
void fpOper_usingStatus(void) { /* ... */ double a = 1e-40, b, c; float x = 0, y; unsigned int rv = _clearfp(); /* Store into y is inexact and underflows: */ y = a; rv = _clearfp(); /* rv has _SW_INEXACT and _SW_UNDERFLOW */ /* zero-divide */ b = y / x; rv = _clearfp(); /* rv has _SW_ZERODIVIDE */ /* inexact */ c = sin(30) * a; rv = _clearfp(); /* rv has _SW_INEXACT */ /* ... */ } |
...
Microsoft Visual Studio 2008 also uses structured exception handling (SEH) to handle floating-point operation. SEH provides more information about the error and allows the programmer to change the results of the floating-point operation that caused the error condition.
Code Block | ||||
---|---|---|---|---|
| ||||
void fp_usingSEH(void) { /* ... */ double a = 1e-40, b, c = 0.1; float x = 0, y; unsigned int rv ; unmask_fpsr(); _try { /* Store into y is inexact and underflows */ y = a; /* divide by zero operation */ b = y / x; /* inexact */ c = sin(30) * a; } _except (_fpieee_flt( GetExceptionCode(), GetExceptionInformation(), fpieee_handler)) { { printf ("fpieee_handler: EXCEPTION_EXECUTE_HANDLER"); } /* ... */ } void unmask_fpsr(void) { unsigned int u; unsigned int control_word; _controlfp_s(&control_word, 0, 0); u = control_word & ~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT); _controlfp_s( &control_word, u, _MCW_EM); return ; } int fpieee_handler(_FPIEEE_RECORD *ieee) { /* ... */ switch (ieee->RoundingMode) { case _FpRoundNearest: /* ... */ break; /* Other RMs include _FpRoundMinusInfinity, * _FpRoundPlusInfinity, _FpRoundChopped */ /* ... */ } switch (ieee->Precision) { case _FpPrecision24: /* ... */ break; /* Other Ps include _FpPrecision53*/ /* ... */ } switch (ieee->Operation) { case _FpCodeAdd: /* ... */ break; /* Other Ops include _FpCodeSubtract, _FpCodeMultiply, * _FpCodeDivide, _FpCodeSquareRoot, _FpCodeCompare, * _FpCodeConvert, _FpCodeConvertTrunc */ /* ... */ } /* * process the bitmap ieee->Cause. * process the bitmap ieee->Enable. * process the bitmap ieee->Status. * process the Operand ieee->Operand1, * evaluate format and Value. * process the Operand ieee->Operand2, * evaluate format and Value. * process the Result ieee->Result, * evaluate format and Value . * The result should be set according to the operation * specified in ieee->Cause and the result format as * specified in ieee->Result. */ /* ... */ } |
...