C/fenv
< C
plik
edytujZnajdujemy plik ( Ubuntu) :
locate fenv.h
Wybieramy plik
/usr/include/fenv.h
który odsyła nas do pliku :
/usr/include/x86_64-linux-gnu/bits/fenv.h
Definicje
edytuj/* Define bits representing the exception. We use the bit positions
of the appropriate bits in the FPU control word. */
enum
{
FE_INVALID =
#define FE_INVALID 0x01
FE_INVALID,
__FE_DENORM = 0x02,
FE_DIVBYZERO =
#define FE_DIVBYZERO 0x04
FE_DIVBYZERO,
FE_OVERFLOW =
#define FE_OVERFLOW 0x08
FE_OVERFLOW,
FE_UNDERFLOW =
#define FE_UNDERFLOW 0x10
FE_UNDERFLOW,
FE_INEXACT =
#define FE_INEXACT 0x20
FE_INEXACT
};
#define FE_ALL_EXCEPT \
(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
Makra
edytujMakra i ich opisy [1]:
/*
FE_INEXACT inexact result : An inexact floating-point exception can occur when a finite floating-point result cannot be exactly represented, as in 2.0 / 3.0
FE_DIVBYZERO division by zero : A zero-divide floating-point exception can occur when a floating-point divide has a finite dividend and a zero divisor, as in 1.0 / 0.0.
FE_UNDERFLOW result not representable due to underflow : An overflow floating-point exception can occur when the magnitude of a finite floating-point result is too large to represent, as in DBL_MAX / DBL_MIN
FE_OVERFLOW result not representable due to overflow : An underflow floating-point exception can occur when the magnitude of a finite floating-point result is too small to represent, as in DBL_MIN / DBL_MAX
FE_INVALID invalid operation : An invalid floating-point exception can occur when a floating-point operation involves an invalid combination of operators and operands, as in 0.0 / 0.0
FE_ALL_EXCEPT bitwise OR of all supported exceptions
*/
Użycie
edytuj- #include <fenv.h>
- -lm
Przykłady
edytuj- musl[2]
feenableexcept
edytuj/// c99 t.c -lm -Wall
// http://jayconrod.com/posts/33/trapping-floating-point-exceptions-in-linux#define _GNU_SOURCE
#include <fenv.h>
int main(void) {
feenableexcept(FE_INVALID |
FE_DIVBYZERO |
FE_OVERFLOW |
FE_UNDERFLOW);
float a = 1., b = 0.;
float c = a/b;
return 0;
}
Uruchamiamy :
./a.out
Wynik :
Błąd w obliczeniach zmiennoprzecinkowych
fetestexcept
edytuj// http://en.cppreference.com/w/c/numeric/fenv/FE_exceptions
// gcc t.c -Wall -std=c99 -lm -frounding-math
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
void show_fe_exceptions(void)
{
printf("exceptions raised:");
if(fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
if(fetestexcept(FE_INEXACT)) printf(" FE_INEXACT");
if(fetestexcept(FE_INVALID)) printf(" FE_INVALID");
if(fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW");
if(fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
feclearexcept(FE_ALL_EXCEPT);
printf("\n");
}
int main(void)
{
printf("MATH_ERREXCEPT is %s\n",
math_errhandling & MATH_ERREXCEPT ? "set" : "not set");
printf("0.0/0.0 = %f\n", 0.0/0.0);
show_fe_exceptions();
printf("1.0/0.0 = %f\n", 1.0/0.0);
show_fe_exceptions();
printf("1.0/10.0 = %f\n", 1.0/10.0);
show_fe_exceptions();
printf("sqrt(-1) = %f\n", sqrt(-1));
show_fe_exceptions();
printf("DBL_MAX*2.0 = %f\n", DBL_MAX*2.0);
show_fe_exceptions();
printf("nextafter(DBL_MIN/pow(2.0,52),0.0) = %.1f\n",
nextafter(DBL_MIN/pow(2.0,52),0.0));
show_fe_exceptions();
}
Kompilujemy
gcc -std=c99 t.c -Wall -lm
uruchamiamy :
./a.out
Wynik :
MATH_ERREXCEPT is set 0.0/0.0 = -nan exceptions raised: FE_INVALID 1.0/0.0 = inf exceptions raised: FE_DIVBYZERO 1.0/10.0 = 0.100000 exceptions raised: sqrt(-1) = -nan exceptions raised: FE_INVALID DBL_MAX*2.0 = inf exceptions raised: FE_INEXACT FE_OVERFLOW nextafter(DBL_MIN/pow(2.0,52),0.0) = 0.0 exceptions raised: FE_INEXACT FE_UNDERFLOW
Źródła
edytuj- ↑ Dinkum C and C++ Libraries buy P.J. Plauger 1989-2002
- ↑ musl is a C standard library implementation for Linux.