math_error(7) Erkennung von Fehlern mathematischer Funktionen

ÜBERSICHT

#include <math.h>
#include <errno.h>
#include <fenv.h>

BESCHREIBUNG

Wenn ein Fehler eintritt, zeigen die meisten Bibliotheksfunktionen diesen Umstand durch Rückgabe eines speziellen Wertes an (z.B. -1 oder NULL). Weil sie normalerweise eine Fließkomma-Zahl zurückgeben, zeigen die in <math.h> deklarierten Funktionen einen Fehler mit anderen Mechanismen an. Es gibt zwei Mechanismen für das Berichten von Fehlern: Der ältere setzt errno; der neuere wird in fenv(3) beschrieben und nutzt den Fließkomma-Ausnahmemechanismus (die Verwendung von feclearexcept(3) und fetestexcept(3), wie im Folgenden skizziert).

Ein portables Programm, das auf Fehler beim Aufruf mathematischer Funktionen prüfen muss, sollte errno auf Null setzen und

feclearexcept(FE_ALL_EXCEPT);
aufrufen, bevor es eine mathematische Funktion aufruft.

Ist nach Abschluss der mathematischen Funktionen errno ungleich Null oder der folgende Aufruf (siehe fenv(3)) gibt einen Wert ungleich Null zurück

fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |
             FE_UNDERFLOW);
trat in der mathematischen Funktion ein Fehler auf.

Im Folgenden werden die Fehlerbedingungen beschrieben, die bei mathematischen Funktionen auftreten können.

Argumentfehler

Ein Argumentfehler liegt vor, wenn einer mathematischen Funktion ein Argument übergeben wird, dessen Wert außerhalb des Definitionsbereichs der Funktion liegt (z.B. ein negatives Argument für log(3)). Wenn ein Argumentfehler vorliegt, geben mathematische Funktionen üblicherweise ein NaN zurück (allerdings geben manche Funktionen in diesem Fall einen anderen Wert zurück); errno wird auf EDOM gesetzt und die Fließkomma-Ausnahme »ungültig« (FE_INVALID) wird ausgelöst.

Polfehler

Ein Polfehler tritt ein, wenn das mathematische Ergebnis einer Funktion exakt unendlich ist (z.B. ist der Logarithmus von 0 minus unendlich). Wenn ein Polfehler eintritt, gibt die Funktion abhängig vom Typ des Funktionsergebnisses (double, float oder long double) den (vorzeichenbehafteten) Wert HUGE_VAL, HUGE_VALF oder HUGE_VALL zurück. Das Vorzeichen des Ergebnisses ist das mathematisch korrekte Vorzeichen für die Funktion. errno wird auf ERANGE gesetzt und die Fließkomma-Ausnahme »Division durch Null« (FE_DIVBYZERO) wird ausgelöst.

Bereichsfehler

Ein Bereichsfehler tritt ein, wenn der Betrag des Funktionsergebnisses nicht im Ergebnisdatentyp der Funktion dargestellt werden kann. Der Rückgabewert der Funktion hängt davon ab, ob der Bereichsfehler ein Überlauf oder ein Unterlauf war.

Ein Fließkomma-Ergebnis läuft über, wenn das Ergebnis endlich, aber zu groß für die Darstellung im Datentyp des Ergebnisses ist. Wenn ein Überlauf eintritt, gibt die Funktion abhängig vom Typ des Funktionsergebnisses (double, float oder long double) den Wert HUGE_VAL, HUGE_VALF oder HUGE_VALL zurück. errno wird auf ERANGE gesetzt und die Fließkomma-Ausnahme »Überlauf« (FE_OVERFLOW) wird ausgelöst.

Ein Fließkomma-Ergebnis läuft unter, wenn das Ergebnis zu klein für die Darstellung im Datentyp des Ergebnisses ist. Wenn ein Unterlauf eintritt, gibt die Funktion typischerweise 0.0 zurück. (C99 fordert, dass der Rückgabewert einer Funktion »ein von der Implementierung definierter Wert sein soll, dessen Betrag nicht größer als der kleinste normalisierte Wert des spezifizierten Typs ist«.) errno kann auf ERANGE gesetzt und eine Fließkomma-Ausnahme »Unterlauf« (FE_UNDERFLOW) kann ausgelöst werden.

Einige Funktionen geben einen Bereichsfehler zurück, wenn der übergebene Argumentwert oder das korrekte Ergebnis der Funktion subnormal sein würden. Ein subnormaler Wert ist von Null verschieden, aber sein Betrag ist so klein, dass er nicht in normierter Form (d.h. mit einer 1 im signifikantesten Bit der Mantisse) dargestellt werden kann. Die Darstellung einer subnormalen Zahl wird eine oder mehrere führende Nullen in der Mantisse enthalten.

ANMERKUNGEN

Die von C99 und POSIX.1 spezifizierte Kennung math_errhandling wird von der Glibc nicht unterstützt. Diese Kennung soll angeben, welches der beiden Verfahren zur Fehlermeldung (errno, Ausnahmen abrufbar über fettestexcept(3)) verwendet wird. Die Standards fordern, dass mindestens eins im Einsatz ist, erlauben aber, dass beide zur Verfügung stehen. Die aktuelle Situation unter Glibc (Version 2.8) ist etwas chaotisch. Die meisten (aber nicht alle) Funktionen lösen bei Fehlern Ausnahmen aus. Einige setzen zusätzlich errno. Einige Funktionen setzen errno, lösen aber keine Ausnahme aus. Einige wenige Funktionen tun weder das Eine noch das Andere. Weitere Einzelheiten finden Sie auf den zugehörigen Handbuchseiten.

Um die komplizierte Anwendung von errno und fetestexcept(3) bei der Fehlerprüfung zu vermeiden, wird oft empfohlen, stattdessen vor jedem Aufruf die Güte der Argumentwerte zu prüfen. So sorgt beispielsweise der folgende Code dafür, dass das Argument für log(3) kein NaN und nicht Null (ein Polfehler) oder kleiner als Null (ein Argumentfehler) ist.

double x, r;
if (isnan(x) || islessequal(x, 0)) {
    /* Fehlerbehandlung für NaN / Polfehler / Argumentfehler */
}
r = log(x);
Die Diskussion auf dieser Seite gilt nicht für die mathematischen Funktionen auf komplexen Zahlen (d.h. solche, die in <complex.h> deklariert werden). Von diesen erwarten C99 and POSIX.1 keine Anzeige von Fehlern.

Die gcc(1)-Option -fno-math-errno bewirkt, dass die ausführbare Datei Implementierungen einiger mathematischer Funktionen verwendet, die schneller als die Standard-Implementierungen sind, aber im Fehlerfall errno nicht setzen. (Die gcc(1)-Option -ffast-math aktiviert ebenfalls -fno-math-errno.) Nach Fehlern kann immer noch mittels fetestexcept(3) gesucht werden.

KOLOPHON

Diese Seite ist Teil der Veröffentlichung 4.06 des Projekts Linux-man-pages. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.

ÜBERSETZUNG

Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Eberhard Schauer <[email protected]> erstellt.

Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.

Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an <[email protected]>.