Zu blöd für Sinus-Reihe



  • Ich soll mit Hilfe von Haskell die immer genauer werdende Sinus-Annäherung als Liste liefern:

    sins x = [x , x - x^3/3! , x - x^3/3! + x^5/5! , ..]
    

    Das Nachfolgeelement habe ich bisher berechnet in dem ich das aktuelle Element genommen habe (beginnend mit dem Startwert x) und dazu:

    x^(2n+1)
    (-1)^n * ----------
               (2n+1)!
    

    addiert habe. Wobei n mit 1 beginnt und dann pro Element eins hoch gezählt wird. Dieses "Muster" habe ich mit der Haskell-Funktion "scanl" abgebildet.

    Leider passiert es mit dieser Formel sehr schnell, dass ich im Nenner hohe Fakultäten berechnen muss (also bereits bei n=10 habe ich 21!) und mir läuft der Haskell-Datentyp Float über.

    Also habe ich mir gedacht ich speichere den alten Wert dieses Additionsterms und berechne den nächsten Additionsterm indem ich ihn mit:

    (-1) * x^2
    -------------
    (2n+2)*(2n+3)
    

    multipliziere. Das verhindert die großen Fakutltäten und sollte so hoffentlich korrekt sein, oder?

    scanl kann ich da nicht mehr direkt verwenden, aber ich habe mich versucht:

    sins :: Float -> [Float] -- Gegeben, ich kann also hier nicht den Typ Float ändern
    sins x = x : foo x x x 0
    
    foo :: Float -> Float -> Float -> Float -> [Float]
    foo x lastValue lastAddTerm n = newValue : foo x newValue newAddTerm (n+1)
        where
        newValue = lastValue + newAddTerm
        newAddTerm = ((-1) * x^2) / ((2*n+2)*(2*n+3))
    

    Der Code lässt sich zwar ausführen, aber
    (a) Konvergiert er viel langsamer als der Code weiter oben
    (b) Konvergiert er imho zur falschen Grenze...so zeigen erste Tests

    Dementsprechend bin ich mir eigentlich sehr sicher etwas falsch gemacht zu haben. Sieht jemand das Problem?

    MfG SideWinder



  • Fehler gefunden. OMG. Meine Definition von newAddTerm muss natürlich noch mit lastAddTerm multipliziert werden... 😮 Sehr lange gesucht 😞

    MfG SideWinder


Anmelden zum Antworten