B.11 <math.h> 

In der Headerdatei <math.h> sind mathematische Funktionen für reelle Gleitpunktzahlen mit dazu passenden Makros und Typen deklariert. <math.h> wurde mit dem C99-Standard erweitert.
In <math.h> finden Sie (seit dem C99-Standard) mit float_t und double_t zwei typedef-Typen, die das Gleitpunktformat darstellen, womit die arithmetischen Ausdrücke vom Typ float bzw. double intern berechnet werden. Von welchem Typ float_t und double_t sind, definiert der Wert des Makros FLT_EVAL_METHOD:
FLT_EVAL_METHOD | float_t entspricht | double_t entspricht |
0 |
float |
double |
1 |
double |
double |
2 |
long double |
long double |
Der Vorteil der Verwendung von float_t und double_t gegenüber der herkömmlichen Verwendung der Typen float, double und long double ist, dass hier die Operanden nicht vor einer arithmetischen Operation konvertiert werden müssen, wie dies häufig der Fall ist.
Folgende Makros sind (ab dem C99-Standard) in der Headerdatei <math.h> vorhanden, um die Gleitpunktwerte zu klassifizieren:
Konstante | Kategorie |
FP_NAN |
NAN steht für Not a Number und bedeutet, dass es sich bei dem Wert um keine gültige Gleitpunktdarstellung handelt. |
FP_NORMAL |
eine Gleitpunktzahl in normaler Darstellung |
FP_INFINITE |
Die Gleitpunktzahl wird als unendlicher Wert dargestellt. |
FP_ZERO |
eine Gleitpunktzahl mit dem Wert 0 |
FP_SUBNORMAL |
eine Gleitpunktzahl, mit der besonders kleine Zahlen dargestellt werden können |
Für die Ermittlung der entsprechenden Kategorie sind folgende Makros definiert:
Makro | Bedeutung |
isnan (x) |
Ist die Gleitpunktzahl gleich FP_NAN, wird 1 zurückgegeben, ansonsten 0. |
isnormal (x) |
Ist die Gleitpunktzahl gleich FP_NORMAL, wird 1 zurückgegeben, ansonsten 0. |
isfinite (x) |
Ist die Gleitpunktzahl eine unendliche Zahl, wird 1 zurückgegeben, ansonsten 0. |
isinf (x) |
Ist die Gleitpunktzahl gleich FP_INFINITE, wird 1 zurückgegeben, ansonsten 0. |
Intern werden alle diese Makros jedoch mithilfe des Makros fpclassify() ausgewertet, das Sie selbstverständlich auch manuell verwenden können:
if ( fpclassify(x) == FP_NAN ) { /* */ } // ... gleichwert zu ... if( isnan(x) ) { /* ... */ }
Auch zum Vergleich von reelen Zahlen sind folgende Makros in der Headerdatei <math.h> vorhanden:
Makro | Bedeutung |
isgreater (x, y) |
x größer als y |
isgreaterequal (x, y) |
x größer als oder gleich y |
isless (x, y) |
x kleiner als y |
islessequal (x, y) |
x kleiner als oder gleich y |
islessgreater (x, y) |
x kleiner als y ODER x größer als y |
isunordered (x, y) |
Sind x und y nicht miteinander vergleichbar, gibt dieses Makro 1 zurück, ansonsten 0. |
Weitere Makros in der Headerdatei <math.h> sind:
Makro | Beschreibung |
HUGE_VAL |
Ist das mathematische double-Ergebnis nicht mehr ohne erheblichen Rundungsfehler durch den Rückgabetyp darstellbar, tritt ein Überlauf auf (Range Error) und liefert das Ergebnis HUGE_VAL zurück. errno wird außerdem auf ERANGE gesetzt. Beispielsweise: // beide Male dieselbe Ausgabe. Beispielsweise : inf printf("%g\n", HUGE_VAL); printf("%g\n", 1.0/0.0); |
HUGE_VALF |
(C99) wie HUGE_VAL, nur für den Typ float |
HUGE_VALL |
(C99) wie HUGE_VAL, nur für den Typ long double |
INFINITY |
(C99) Je nach Implementierung steht dieses Makro für einen konstanten Ausdruck vom Typ float, der positiv unendlich bzw. unendlich ohne Vorzeichen ist, oder das Makro entspricht einem Überlauf eines konstanten float-Wertes, wobei der Compiler eine Fehlermeldung erzeugt. |
NAN |
(C99) NAN steht für Not A Number und wird ausgegeben, wenn der Wert keine gültige Gleitpunktzahl ist. Dieses Makro ist nur dann definiert, wenn die Implementation auch NAN unterstützt. Beispielsweise: // beide Male dieselbe Ausgabe. Beispielsweise : nan printf("%g\n", NAN); printf("%g\n", sqrt(-1)); |
Jetzt fehlen natürlich noch die Funktionen der Headerdatei <math.h>. Bei der Tabelle der Gleitpunktfunktionen werden hier nur die double-Versionen aufgelistet. Wenn Sie mit float oder long double arbeiten, müssen Sie zum Funktionsnamen lediglich den Buchstaben f oder l hinzufügen.
Funktion in <math.h> | Beschreibung |
double cosh( double z );1) double sinh( double z );1) double tanh( double z);1) |
Hyperbolische Funktionen |
double acos( double z ); |
Arcuscosinus |
double asin( double z ); |
Arcussinus |
double atan( double z ); |
Arcustangens |
double cos( double z ); |
Cosinus |
double sin( double z ); |
Sinus |
double tan( double z); |
Tangens |
double cosh( double z); |
Cosinus hyperbolicus |
double sinh( double z); |
Sinus hyperbolicus |
double tanh( double z); |
Tangens hyperbolicus |
double exp( double z); |
Exponentialfunktion berechnen |
double log( double z); |
Logarithmus von z zur Basis e = 2.71828... |
double sqrt( double z); |
Quadratwurzel |
double fabs( double z); |
Absolutwert |
double pow( double z1, double z2 ); |
Potenz z1z2 |
double atan2( double x1, double x2 ); |
Arcustangens von x1 und x2 |
double exp(double x ); double exp2(double x ); 1) double frexp( double x, int x2 ); double ldexp( double x, int exp ); double scalbn( double x, int n );1) double scalbln( double x, long int n );1) |
Exponentialfunktionen |
double log(double x); double log10(double x) double log1p(double x);1) double log2(double x);1) double logb(double x);1) int ilogb(double x);1) |
Logarithmusfunktionen |
double fabs(double x); |
Absolutwert |
double nextafter( double x, double y);1) double nexttoward( double x, long double y);1) |
nächste darstellbare Zahl |
double fma( double x, double y, double z);1) |
Multiplikation und Addition (x*y+z) |
double fdim ( double x, double y );1) |
positive Differenz |
double trunc(double x);1) long long int llround( double x); 1) long int lround(double x);1) double round(double x);1) long long int llrint( double x ); 1) long int lrint(double x);1) double rint(double x);1) double nearbyint(double x);1) |
Rundungsfunktionen |
double floor(double x); double ceil(double x); |
nächste Ganzzahl runden |
double modf( double1 x1, double2 *x2); |
Zerlegt den Wert von x1 in einen gebrochenen und einen ganzzahligen Wert. Der ganzzahlige Wert (Vorkommateil) befindet sich dann in der Adresse von x2. |
int fmod( double x1, double x2 ); double remainder( double x, double y);1) double remquo( double x, double y, int *quo); 1) |
Rest einer Division |
double hypot( double x, double y ); double cbrt(double x);1) |
Wurzelfunktionen |
double erf(double x);1) double erfc(double x);1) |
Fehlerfunktionen zur Normalverteilung |
double fmin( double x, double y); double fmax( double x, double y); |
Minimum und Maximum |
double lgamma(double x);1) double tgamma(double x);1) |
Gammafunktionen |
double copysign( double x, double y);1) |
Vorzeichen zuordnen |
double nan( const char *tagp);1) |
ein NaN erzeugen |
1) Diese Funktionen wurden erst mit dem C99-Standard eingeführt. |
Für die Funktion fma(x, y, z) können außerdem in der Headerdatei <math.h> seit dem C99-Standard die Makros FP_FAST_FMA, FP_FAST_FMAF, FP_FAST_FMAL definiert sein. Wenn diese definiert sind, dann bedeutet dies, dass die Ausführung der Funktion schneller ist als die Ausführung einer gewöhnlichen Multiplikation, gefolgt von einer Addition mit Operatoren (beispielsweise x*y+z). Dies ist dann der Fall, wenn die Funktion fma() spezielle Maschinenbefehle verwendet. FP_FAST_FMA ist die double-Version, FP_FAST_FMAF die float-Version und FP_FAST_FMAL die Version für long double.
Auch für Funktion ilogb(x) gibt es mit FP_ILOGB0 und FP_ILOGBNAN zwei Makros. FP_ILOGB0 wird ausgegeben, wenn das Argument x den Wert 0 hat. FP_ILOGBNAN hingegen bedeutet, dass x keine gültige Gleitpunktzahl ist. FP_ILOGB0 kann entweder den Wert -INT_MAX oder INT_MIN haben und FP_LOGBNAN kann den Wert INT_MAX oder INT_MIN annehmen.
Folgende Makros machen die Übersicht zur Headerdatei <math.h> jetzt komplett (C99):
// Konstante mit dem Wert 1 MATH_ERRNO // Konstante mit dem Wert 2 MATH_ERREXCEPT
Diese Konstanten werden als Bit-Masken verwendet, um den Inhalt von math_errhandling. der externen Variablen oder eines Makros vom Typ int zu ermitteln. Ist beispielsweise der Ausdruck
if ( math_errhandlich & MATH_ERRNO ) { // Ein Fehler ist aufgetreten; errno auslesen }
nicht null, dann können Sie daraus schließen, dass bei einer Berechnung ein Fehler aufgetreten ist. Mit der Fehlervariablen errno können Sie jetzt ermitteln, ob es sich hierbei um einen Domain error (EDOM) oder Range error (ERANGE) handelt.
Selbiges lässt sich mit den Exceptions der Gleitpunkt-Umgebung verwenden:
if ( math_errhandlich & MATH_ERREXCEPT ) { // Eine Exception ist aufgetreten. // Mögliche Exceptions finden Sie in <fenv.h>. }
Wenn die Implementierung Exceptions der Gleitpunkt-Umgebung unterstützt, können Sie diese mithilfe der Makros FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW und FE_UNDERFLOW aus der Headerdatei <fenv.h> und der Funktion fetestexcept() auswerten. Mehr dazu habe ich bereits in Abschnitt 20.3.7, »Zugriff auf die Gleitpunktumgebung – <fenv.h>« geschrieben.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.