Optimales epsilon



  • Hallo,

    für numerisches Ableiten braucht man ja eine geeignete Schrittweite h. Dafür verwende ich diese Funktion (frei nach Wikipedia):

    template <typename T> T get_optimal_epsilon(T const &x)
    {
    	return std::sqrt(std::numeric_limits<T>::epsilon())*std::abs(x);
    }
    

    Worauf im Artikel aber nicht eingegangen wird: Je näher x an 0 ist, desto schlechter wird das epsilon - für x == 0 ist epsilon ebenfalls 0, was natürlich keinen Sinn mehr ergibt.

    Wie kann/soll/muss man die Funktion erweitern damit dieser Fall vernünftig abgedeckt wird?



  • happystudent schrieb:

    Wie kann/soll/muss man die Funktion erweitern damit dieser Fall vernünftig abgedeckt wird?

    Der Fall ist schon vernünftig abgedeckt. 0 kann exakt dargestellt werden, daher braucht man auch kein epsilon, daher finde ich epsilon = 0 für x == 0 vernünftig.



  • nwp3 schrieb:

    Der Fall ist schon vernünftig abgedeckt. 0 kann exakt dargestellt werden, daher braucht man auch kein epsilon, daher finde ich epsilon = 0 für x == 0 vernünftig.

    Ne das ist für numerisches Ableiten nicht vernüntig (und darum gehts ja hier und in dem Wikipedia Artikel). Die Berechnungsvorschrift dafür lautet ja:

    ddxf(x)f(x)f(xh)h\frac{d}{dx}f(x) \approx \frac{f(x) - f(x - h)}{h}

    wobei h ein möglichst optimales epsilon sein sollte um den Fehler klein zu halten. Wenn h jetzt Null ist habe ich 0/0, also einen undefinierten Ausdruck -> ganz schlecht.



  • Errechnet man sich das h nicht durch gegebene Parameter?
    Z.B. willst du für einen Bereich [a, b) ableiten (oder integrieren) und zwar mit n Punkten, dann könntest du h = (b-a)/n setzen.

    Edit: das war Bullshit



  • Skym0sh0 schrieb:

    Errechnet man sich das h nicht durch gegebene Parameter?
    Z.B. willst du für einen Bereich [a, b) ableiten (oder integrieren) und zwar mit n Punkten, dann könntest du h = (b-a)/n setzen.

    Äh nein, was für Parameter? Die Ableitung (!= integrieren) berechnet man ja an einer Stelle (nicht in einem Interval). In C++ ausgedrückt:

    double f(double x) { return x*x*x; } // f(x) = x^3
    
    double derivative(std::function<double(double)> const &f_, double x_, double epsilon_)
    {
        return (f_(x_) - f_(x_ - epsilon_))/epsilon_;
    }
    
    int main()
    {
        std::cout << derivative(f, 2.0, 1.0e-7); // Ableitung von f an der Stelle 2.0 mit einem epsilon von 1.0e-7
    }
    

    Problem dabei ist das epsilon, das ja in Abhängigkeit des Wertes x unterschiedlich groß sein muss um optimal genaue Ergebnisse zu erhalten.



  • für x=0 kannst du dann das Maschinen-Epsilon nehmen:

    template <typename T> T get_optimal_epsilon(T const &x) 
    { 
        return x==0 ?
           std::numeric_limits<T>::epsilon() :
           std::sqrt(std::numeric_limits<T>::epsilon())*std::abs(x); 
    }
    


  • happystudent schrieb:

    Skym0sh0 schrieb:

    Errechnet man sich das h nicht durch gegebene Parameter?
    Z.B. willst du für einen Bereich [a, b) ableiten (oder integrieren) und zwar mit n Punkten, dann könntest du h = (b-a)/n setzen.

    Äh nein, was für Parameter? Die Ableitung (!= integrieren) berechnet man ja an einer Stelle (nicht in einem Interval).

    Ja verwechselt mim Integrieren. War etwas durcheinander, weil wir grad in der Uni ne ähnliche Aufgabe halt mit Integralen machten.



  • Skym0sh0 schrieb:

    Ja verwechselt mim Integrieren. War etwas durcheinander, weil wir grad in der Uni ne ähnliche Aufgabe halt mit Integralen machten.

    Np, immerhin hast du integrieren und nicht "aufleiten" gesagt. Da rastet unser Prof immer aus 😃

    oenone schrieb:

    für x=0 kannst du dann das Maschinen-Epsilon nehmen:

    template <typename T> T get_optimal_epsilon(T const &x) 
    { 
        return x==0 ?
           std::numeric_limits<T>::epsilon() :
           std::sqrt(std::numeric_limits<T>::epsilon())*std::abs(x); 
    }
    

    He, scheint zu klappen. Danke 👍

    Mal noch ne Frage, optimiert der Compiler das std::sqrt(std::numeric_limits<T>::epsilon()) eigentlich weg (ist ja ne konstante) oder sollte ich das lieber in einer static Variable ablegen?



  • Dumme Frage aber:
    Was soll sqrt(eps) sein / bezwecken? eps ist ja schon der kleinste Wert...



  • Wurzel aus 0 < Zahl < 1 wird größer? Habe aber auch den Sinn nicht verstanden.



  • nwp3 schrieb:

    Wurzel aus 0 < Zahl < 1 wird größer? Habe aber auch den Sinn nicht verstanden.

    Oh, wie dumm, natürlich nicht. Kommt vom ganzen Apfelkuchen!



  • oenone schrieb:

    für x=0 kannst du dann das Maschinen-Epsilon nehmen:

    template <typename T> T get_optimal_epsilon(T const &x) 
    { 
        return x==0 ?
           std::numeric_limits<T>::epsilon() :
           std::sqrt(std::numeric_limits<T>::epsilon())*std::abs(x); 
    }
    

    Naja, irgendwie sollte die Funktion schon den Anschein von Stetigkeit bewahren, oder?

    Wikipedia bezieht sich an der Stelle auf Numerical Recipes in C: http://www2.units.it/ipl/students_area/imm2/files/Numerical_Recipes.pdf Abschnitt 5.7. Ich würd dort mal nachlesen und versuchen, das nachzuvollziehen.



  • Bashar schrieb:

    Wikipedia bezieht sich an der Stelle auf Numerical Recipes in C: http://www2.units.it/ipl/students_area/imm2/files/Numerical_Recipes.pdf Abschnitt 5.7. Ich würd dort mal nachlesen und versuchen, das nachzuvollziehen.

    Ja, das kenn ich schon, leider steht da nix genaueres zu dem Thema außer "except near x = 0 where some other estimate of the typical x scale should be used". Was für eine Schätzung benutzt werden sollte lassen sie aber einfach mal unter den Tisch fallen...



  • Apfelkuchen um 4 schrieb:

    Dumme Frage aber:
    Was soll sqrt(eps) sein / bezwecken? eps ist ja schon der kleinste Wert...

    Nein, ist es nicht.

    Machine epsilon (the difference between 1 and the least value greater than 1 that is representable).



  • happystudent schrieb:

    Ja, das kenn ich schon, leider steht da nix genaueres zu dem Thema außer "except near x = 0 where some other estimate of the typical x scale should be used". Was für eine Schätzung benutzt werden sollte lassen sie aber einfach mal unter den Tisch fallen...

    Interessant dabei finde ich vor allem, dass das x in der Formel eigentlich nicht für das Argument steht, sondern für die Krümmung der Funktion, und das Argument nur aus pragmatischen Gründen benutzt wird, weil man meistens die Krümmung nicht kennt.



  • Bashar schrieb:

    Interessant dabei finde ich vor allem, dass das x in der Formel eigentlich nicht für das Argument steht, sondern für die Krümmung der Funktion, und das Argument nur aus pragmatischen Gründen benutzt wird, weil man meistens die Krümmung nicht kennt.

    Ja, es ist eine Approximation des wirklich besten epsilons... Problem ist auch dass es nicht nur für x exakt 0 Probleme gibt, sondern schon in der näheren Umgebung von 0...


Log in to reply