Kosinus mit Taylorreihe.



  • Guten Abend,
    ich soll cos(x) mit Hilfe der Taylorreihe berechnen.
    Einschränkung ist, das die vorgegebene Funktionen nur den Kosius bis 33 berechnen kann. also nur bis x^33/33!

    Ich hab mir schon etwas überlegt, aber leider funktioniert der Code nicht.

    #include <iostream>
    #include <cmath>
    
    unsigned int fakultaet (unsigned int n);
    unsigned int fakultaet (unsigned int n){
    //n muss kleiner als 34 sein -> n < 34
    
    // Berechnen der Fakultät
    unsigned int fakultaet = 1;
    for(unsigned int i = 2; i <= n; ++i ) {
        fakultaet *= i;
        }
        // Ausgabe
    return fakultaet;
    }
    
    int main(){
    
    double eingabe;
    
    std::cin >> eingabe;
    
    double x = eingabe * 3.1415/180;
    
    std::cout << x << '\n';
    
    int z=2;
    int n=2;
    double cosi = 1 - ((pow(x,2))/fakultaet(n));
    std::cout << "cosi: " << cosi << '\n';
    
    for (int i=1; i < 17; i++){
        cosi = cosi + ((pow(-1,z)) * ((pow(x,2*n))/fakultaet(2*n)));
        n++;
        z++;
        return cosi;
    }
    std::cout << cosi << '\n';
    
    }
    

    sorry wenn es ein bisschen schlampig aussieht.
    bitte nicht von den Ausgaben stören lassen...



  • for (int i=1; i < 17; i++){
        cosi = cosi + ((pow(-1,z)) * ((pow(x,2*n))/fakultaet(2*n)));
        n++;
        z++;
        return cosi;// <-- das ist wohl ungewollt, du verlässt an dieser Stelle die Hauptfunktion!
    }
    


  • double Cos(double x){
      double arg = 1, cosi = 0, x2 = x*x;
      long long int fak = 1; 
      for (int i = 0; i < 17; ++i)
      {
          cosi += arg / fak;
          fak *= -(2*i + 1) * (2*i + 2);
          arg *= x2;
      } 
      return cosi;
    }
    


  • dfsdfsdf schrieb:

    for (int i=1; i < 17; i++){
        cosi = cosi + ((pow(-1,z)) * ((pow(x,2*n))/fakultaet(2*n)));
        n++;
        z++;
        return cosi;// <-- das ist wohl ungewollt, du verlässt an dieser Stelle die Hauptfunktion!
    }
    

    ok verstehe.
    Wenn ich das return weglasse bekomme ich jetzt ein -inf als ausgabe. Ist ja schonmal besser als nichts aber immer noch nicht zufriedenstellend 😃



  • Dann laß dir doch mal innerhalb der Schleife 'cosi' ausgeben.



  • du brauchst weder pow(), um -1 zu potenzieren, noch die Fakultät und x^n in jedem Schleifendurchlauf wieder zu berechnen. Das ist ineffizient und in deinem Fall falsch. Wie man es effizient und richtig macht, habe ich ja geschrieben.


  • Mod

    zufallswert schrieb:

    Wie man es effizient und richtig macht, habe ich ja geschrieben.

    Dein Code hat allerdings das gleiche Problem. Schon mal angeschaut, wie groß 34! ist?



  • mit

    __int128 fak = 1;
    

    oder

    double fak = 1;
    

    geht's.


  • Mod

    zufallswert schrieb:

    mit

    __int128 fak = 1;
    

    oder

    double fak = 1;
    

    geht's.

    Die Frage ist, wieso überhaupt eine separate Variable benötigt wird. Das passt alles in arg rein.



  • mit 64- oder 128-Bit integer Fakultät kann man länger exakt rechnen als mit 52 Bit Mantisse.



  • Da es hier jetzt etwas kompliziert wird und die Aufgabe aus dem ersten Semester stammt, hier mal die Lösung für Anfänger.
    Ich habe es gestern Nacht noch raus gefunden. Wie camper geschrieben hat, war das Problem, das ich mich bei den Schleifendurchläufen vertan hab. Die Schleife darf nur bis 16 gehen nicht bis 17! Dann sollte der Code funktionieren. Beim letzten Schleifendurchlauf konnte die Fakultät nicht berechnet werden und es kommt 0 raus. (Durch null kann man nicht teilen)
    @zufallswert Es kann zwar sein, dass dein Code deutlich sinnvoller, und effizienter ist. Die Aufgabe, war jedoch sich an die Summenformel zu halten und die Fakultät mit der gegebenen Funktionen zu berechnen.
    Danke für die Hilfe.



  • n! will man ja auch gar nicht haben, aondern 1/n!
    Also einen Wert, der immer kleiner wird.

    Irgendwann ist der Anteil an der Summe aber so gering, dass man den gar nicht mehr mitbekommt.

    Da das Ergebnis ein double ist, spielt es auch keine Rolle, ob int128 genauer ist

    Da man aber jeden neuen Summanden aus dem vorhergehenden berechnen kann, benötigt man das gar nicht und

    camper schrieb:

    Das passt alles in arg rein.



  • jein. Die Taylor-Approximation für cos ist konzeptuell ein Polynom, deren Argument eine Matrix oder allgemeiner ein linearer Operator ist.

    Der Fall cos(x) mit x double ist lediglich Spezialfall mit Argument = 1 x 1 -Matrix.

    Allgemein ist der Vorfaktor (-1)^(2n + 1) / (2n + 1)! ein Skalar, das Argument x hingegen ein Operator. Also konzeptuell verschiedene Datentypen. Der Argument-Typ muß bspw. keine Division unterstützen, der Skalar-Typ aber schon.

    Durch die Trennung von Vorfaktor und Argument bleibt der Algorithmus generisch und kann ohne Änderung auf den Fall x = Matrix oder x = komplexe Zahl angewendet werden.



  • zufallswert schrieb:

    Allgemein ist der Vorfaktor (-1)^(2n + 1) / (2n + 1)! ein Skalar, das Argument x hingegen ein Operator.

    Irgendwas stimmt hier doch nicht. 2n+1 ist immer ungerade und du meinst doch nicht: 1(2n+1)!\frac{-1}{(2n+1)!}
    Die Summe ist doch abwechselnd + und -, also \sum\limits_n (-1)^n \times \dots



  • ja, stimmt. (-1)^n / (2n)! vor x^n beim cos.


Anmelden zum Antworten