tan^-1 (z) mit Hilfe von Euler oder Maclaurian berechnen



  • Hallo,

    hab da mal ein paar Formeln gefunden, um den 'Inveres Tangent' zu berechnen. Ich weiß, dass es sowas schon gibt, aber ich wollt diese Formeln trotzdem mal in C implementieren:
    http://mathworld.wolfram.com/InverseTangent.html

    zum einen die von maclaurin und dann noch die von castellanus, die auf der von euler aufbaut. hab mal damit angefangen, ist aber warscheinlich genausofalsch, wie die ergebnisse die ich nachher erhalte.
    hier mal die von euler

    double inv_tan_eul(double x)
    {
    	double y=(x*x)/(x*x+1);//das y aus der Formel
    	double m=1;//die komplette klammer auf der rechten seite
    	double l=1;//der koeffizient von y^n
    
    	for(int i=2; i<1000; i=i+2)
    	{
    		l*=(double)i/(i+1);
    		m+=l * pow(y, i/2);
    	}
    	return m * (y/x);
    }
    

    und dann noch die, die auf der maclaurin serie aufbaut:

    double inv_tan_mac(double z)
    {
    	double res = z;//das ergebnis, die erste zahl in der reihe ist ja z
    	short s=0;//abwechselnd wird immer addiert und subtrahiert.
    
    	for(int i=3; i<1000; i=i+2)
    	{
    		if(s)
    			res += pow(z, i) / i;
    		else
    			res -= pow(z, i) / i;
    		s=1-s;
    	}
    
    	return res;
    }
    

    man muss nur noch die math.h includieren, dann sollts eigentlich klappen - das kompilieren zumindest.

    Bin euch für jeden Verbesserungsvorschlag dankbar!



  • Erster Verbesserungsvorschlag: Lass es und rechne mit atan() 😃

    Zweitens: Ich bin mir nicht sicher, wie gut dein Abbruchkriterium wirklich ist - womöglich bist du nach den 500 Schritten noch zu weit vom Ziel entfernt (oder anderes Extem - du hast das Ziel bereits nach 100 Schritte erreicht und verschwendest anschließend nur sinnlos Rechenzeit).

    Drittens: Was meinst du mit "die Ergebnisse sind falsch"? Hast du auch berücksichtigt, daß Mathematiker im Bogenmaß rechnen?



  • Bin euch für jeden Verbesserungsvorschlag dankbar!

    short s=0;//abwechselnd wird immer addiert und subtrahiert.
    
        for(int i=3; i<1000; i=i+2)
        {
            if(s)
                res += pow(z, i) / i;
            else
                res -= pow(z, i) / i;
            s=1-s;
        }
    

    besser gefiele mir:

    short s = 1;
        for(int i=3; i<1000; i=i+2)
            res += (s = -s) * pow(z, i) / i;
    


  • CStoll schrieb:

    Erster Verbesserungsvorschlag: Lass es und rechne mit atan() 😃

    Yup den kenn ich ja, aber das wollte ich gerade nicht machen.

    CStoll schrieb:

    Zweitens: Ich bin mir nicht sicher, wie gut dein Abbruchkriterium wirklich ist - womöglich bist du nach den 500 Schritten noch zu weit vom Ziel entfernt (oder anderes Extem - du hast das Ziel bereits nach 100 Schritte erreicht und verschwendest anschließend nur sinnlos Rechenzeit).

    Ne hab einfach mal ne fiktive Zahl eingegeben. Also bei der Maclaurin Reihe weiss ich, dass es auch nach einigen 100 000 schritten immer nur noch genauer wird (müsste man sich dann aber wohl in C++ nen eigenen datentypen basteln).

    CStoll schrieb:

    Drittens: Was meinst du mit "die Ergebnisse sind falsch"? Hast du auch berücksichtigt, daß Mathematiker im Bogenmaß rechnen?

    also der Formel nach zu urteilen sollte ich so den tan^-1 rausbekommen, für den tangens etc. sehen die Formeln ja dann wider anders aus. Und mit "falsch" meine ich, dass eine Überprüfung mit dem Taschenrechner ein anderes Ergebnis liefert, das garantiert NICHT auf einen Rundugsfehler zurückzuführen ist (z.B. ~0.8 - ~11.2).

    @cheopz: Ja da hast du recht, der Code spricht mich auch mehr an, danke für den Vorschlag 😉



  • Elviss schrieb:

    CStoll schrieb:

    Zweitens: Ich bin mir nicht sicher, wie gut dein Abbruchkriterium wirklich ist - womöglich bist du nach den 500 Schritten noch zu weit vom Ziel entfernt (oder anderes Extem - du hast das Ziel bereits nach 100 Schritte erreicht und verschwendest anschließend nur sinnlos Rechenzeit).

    Ne hab einfach mal ne fiktive Zahl eingegeben. Also bei der Maclaurin Reihe weiss ich, dass es auch nach einigen 100 000 schritten immer nur noch genauer wird (müsste man sich dann aber wohl in C++ nen eigenen datentypen basteln).

    Da würde ich wohl eher die Berechnung abbrechen, wenn die nächstfolgenden Summanden zu klein werden für die double-Genauigkeit.

    CStoll schrieb:

    Drittens: Was meinst du mit "die Ergebnisse sind falsch"? Hast du auch berücksichtigt, daß Mathematiker im Bogenmaß rechnen?

    also der Formel nach zu urteilen sollte ich so den tan^-1 rausbekommen, für den tangens etc. sehen die Formeln ja dann wider anders aus. Und mit "falsch" meine ich, dass eine Überprüfung mit dem Taschenrechner ein anderes Ergebnis liefert, das garantiert NICHT auf einen Rundugsfehler zurückzuführen ist (z.B. ~0.8 - ~11.2).

    Rundungsfehler vielleicht nicht, aber womöglich die falsche Einheit verwendet (*grübelt* wobei der genannte Unterschied wiederum zu klein ist für eine Verwechslung von Grad und Radiant).



  • habe beide funktionen (euler und dann den code von cheopz) mal bis tausend durchlaufen lassen mit 10 als parameter.

    Macluarin       -1.#INF
    Euler           1.46861
    Taschenrechner  84.28940686
    

    😮
    also der erste verkraftets aus irgeneinem Grund nicht, beim zweiten wirds ab 10 000 schleifendurchläufen dann nichmehr genauer (nähert sich zwar an irgendeinen wert an aber der ist weder ähnlich dem atan(10), noch dem tan(10)=0.176...)

    Aber der eigentliche Grund warum ich den Code gepostet habe, ist weil ich wissen wollte ob mein C Code der Vorlage entspricht, oder ob sich da irgendwelche Fehler eingeschlichen haben (bzw. es haben sich ja welche eingeschlichen, da das ergebnis nicht korrekt ist).



  • Sorri für den Doppelpost, aber ich habe jetzt mal atan (math.h) zum vergleichen gewählt und ab 10 000 durchläufen sieths so aus: atan(10)==inv_tan_eul(10)==1.7113

    CStoll schrieb:

    Drittens: Was meinst du mit "die Ergebnisse sind falsch"? Hast du auch berücksichtigt, daß Mathematiker im Bogenmaß rechnen?

    Das hätte ich vielleicht doch besser beherzigen sollen 🙄

    Jedenfalls sieht es so aus, als ob diese Methode klappen würde, danke nochmals dafür.



  • Bei MacLaurin hast du womöglich noch eine Division durch 0 eingebaut, die dir das Ergebnis zerschießen könnte. Aber der Unterschied zwischen Euler und Taschenrechner ist wirklich die falsche Einheit - die Euler-Formel liefert den ArcTan in Radiant, dein Taschenrechner in Grad (und wenn ich den Windows Rechner auf "Rad" umstelle, ergibt arcttan(10) ein Ergebnis von 1,4711276743037345918528755717617 - das liegt schon deutlich näher an deinem Wert ;)).


Anmelden zum Antworten