Laden...

float, double Arithmetik: Epsilon berechnen

Erstellt von Siassei vor 14 Jahren Letzter Beitrag vor 14 Jahren 6.895 Views
Information von herbivore vor 12 Jahren

Dies ist ein Thread, auf den aus der FAQ verwiesen wird. Bitte keine weitere Diskussion, sondern nur wichtige Ergänzungen und diese bitte knapp und präzise. Vielen Dank!

S
Siassei Themenstarter:in
401 Beiträge seit 2008
vor 14 Jahren
float, double Arithmetik: Epsilon berechnen

Hallo,

ich muss in einem Anwendungsfall den relativen max. Fehler abschätzen.
Es werden endlich viele Grundrechenoperationen +, - , *, /, ^, .... durchgeführt. Nun soll die Stelle ermittelt werden, die im Worst-Case noch korrekt ist. Leider habe ich kein Informatik-Mathe bekommen und kann im Web keine Informationen finden.

Kann mir jemand helfen, den Fehler abzuschätzen? Ich brauche das für meine kleine Mathe-Lib 😃
Achja, double muss nicht 64bit groß sein. Im Hintergrund durchaus 80bit oder mehr. Quelle 1

Im Forum stieß ich auf folgendes:

public static double Epsilon()
        {
            double tau = 1.0;
            double alt = 1.0;
            double neu = 0.0;

            while (neu != alt)
            {
                tau *= 0.5;
                neu = alt + tau;
            }

            return 2.0 * tau;
        }

Gilt das nur für C#, oder allgemein? Somit auch für C++ native.

Gruß,
Thomas

6.911 Beiträge seit 2009
vor 14 Jahren

Hallo,

Achja, double muss nicht 64bit groß sein.

Wenn die Programmiersprache IEEE 754 konform dann ist ein double 64bit - nicht mehr und nicht weniger.

Gilt das nur für C#, oder allgemein? Somit auch für C++ native.

Das ist allgemein gültig - also sprachinvariant.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Siassei,

Es werden endlich viele Grundrechenoperationen +, - , *, /, ^, .... durchgeführt.

es gibt kein festes Epsilon, das man unabhängig von der Berechnung verwenden kann. Der Fehler einer beliebigen Berechnung kann grundsätzlich beliebig groß werden. Eine Zahl minus eine fast gleichgroße Zahl mal eine sehr große Zahl führt typischerweise auch zu einem großen Fehler. Es ist also nicht mal gesagt, dass Epsilon immer kleiner eins ist.

Es gibt aber mathematische Regeln, mit denen man den (maximalen) Fehler abschätzen kann ==> Fehlerabschätzung.

herbivore

S
Siassei Themenstarter:in
401 Beiträge seit 2008
vor 14 Jahren

Danke für eure Antwort 😃

@herbivore Eine manuelle Fehlerabschätzung ist natürlich möglich. Aber da wird mir der Compiler einen Strich durch die Rechnung machen. Unterschiedliche Optimierungen + Hersteller (.NET, Mono, was weiß ich) machen das so gut wie unmöglich.

Wenn die Programmiersprache IEEE 754 konform dann ist ein double 64bit - nicht mehr und nicht weniger. Da habe ich mich wohl falsch ausgedrückt. Nach aussen gilt dies für die meisten Sprachen. Im Hintergrund wird oftmals mit höherer Auflösung gerechnet, sofern ein Chip die nötigen Befehle besitzt.

Ich kenne nur Java in Version 1.1, wo dieses Verhalten nicht implementiert ist. Ab Version 1.2 gibt es ein Schlüsselwort, aber das kennt so gut wie keiner.
C# .NET rechnet mit einer höheren Auflösung als 64bit im Hintergrund. Ansonsten wäre das Beispiel nicht möglich.

Epsilon von mir ist 2,22044604925031E-16
Epsilon eigebatu ist 4,94065645841247E-324

Edit: Hier wird auf die kleinste, darstellbare Zahl (von Double) runter gerechnet. Das kann nicht gut sein. Komischerweiße wird das hier im Forum empfohlen. Oder ist das ein Fall für Copy&Paste?

C++ gibt bei mir zwei identische Werte aus. (GCC 4.4.1 - Linux)

2.22045e-16 // Berechnet
2.22045e-16 // numeric_limits<double>::epsilon()
#include <iostream>
#include <limits>

using namespace std;

static double
Epsilon( )
{
    double tau = 1.0;
    double alt = 1.0;
    double neu = 0.0;

    while (neu != alt)
    {
        tau *= 0.5;
        neu = alt + tau;
    }

    return 2.0 * tau;
}


int
main(int len, char** args)
{
    cout << Epsilon( ) << endl;
    cout << numeric_limits<double>::epsilon( ) << endl;

    return 0;
}

Edit: Falschen Link

6.911 Beiträge seit 2009
vor 14 Jahren

Epsilon von mir ist 2,22044604925031E-16
Epsilon eigebatu ist 4,94065645841247E-324
Edit: Hier wird auf die kleinste, darstellbare Zahl (von Double) runter gerechnet. Das kann nicht gut sein. Komischerweiße wird das hier im Forum empfohlen. Oder ist das ein Fall für Copy&Paste?

Im Original wo das vorkommt (ist von mir) steht da noch mehr 😉 Nämlich dass die Epsilon-Konstante der eingebauten Fließkommadatentypen bei .net nicht dem in der Numerik gebräuchlichen Epsilon (1+eps=1) entspricht sondern der kleinsten darstellbaren Fließkommazahl.
Somit ist das Zitat inkomplett.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Gelöschter Account
vor 14 Jahren

C# .NET rechnet mit einer höheren Auflösung als 64bit im Hintergrund.

noe.

intel haut seine floats&doubles in den FPU, welcher mit 90 bit rechnet. das würde er aber auch in c, c++ oder java machen. amd hanhabt das ein klein wenig anders, was aber ebenfalls irrelevant sein sollte. du kannst nciht für alle möglichen arten von cpu´s eine außnahme programmieren, da du so nicht zukunftssicher programmieren kannst. gehe einfach vom worst case aus und das sind 64 bit für double, denn diese sind wenigstens garantiert.