Cosinus und Sinus

Sinus und Cosinus eines Winkels können berechnet werden, indem der Winkel zuerst mehrfach halbiert wird, bis er kleiner als eine gewählte Grenze ist, dann für den kleinen Winkel der Tangens anhand der Padé-Approximation

  tan(x) = x(1+(x²/105-1)(x/3)²)/(1+(x²/7-4)(x/3)²)

berechnet wird, danach mittels der Folgerung

  tan(2x) = 2tan(x)/(1−tan²(x))

des Additionstheorems der Tangens für den ursprünglichen Winkel berechnet wird und man zum Schluss aus dem Tangens den Cosinus

  cos(x) = (1-tan²(x))/(1+tan²(x))

und den Sinus

  sin(x) = 2tan(x)/(1 + tan²(x))

ermittelt.

Es ergibt sich folgender Code:


(setq cosine-sine
  (letrec

#| half za until it is smaller than d |#
    ((repeated-halving
      (lambda (d za k)
        (if
          (less? za d)
          (list za k)
          (repeated-halving d (/ za 2) (+ k 1)))))

#| padé approximation of tangent |#
     (pade
       (lambda (za)
         (let
           ((zaza (* za za)))
           (let
             ((zaza9 (/ zaza 9)))
             (* za
               (+ 1 (* (- (/ zaza 105) 1) zaza9))
               (/ 1 (+ 1 (* (- (/ zaza 7) 4) zaza9))))))))

#| identity for double angle |#
     (double-angle-identity
       (lambda (ta k)
         (if
           (less? k 1)
           ta
           (double-angle-identity
             (/ (* 2 ta) (- 1 (* ta ta)))
             (- k 1)))))

#| tangent to cosine and sine |#
     (tangent-to-cosine-and-sine
       (lambda (ta)
         (let
            ((tata (* ta ta)))
            (list
              (/ (- 1 tata) (+ 1 tata))
              (/ (* 2 ta) (+ 1 tata)))))))

#| repeated halving, tangent approximation, then calculate cosine and sine |#
    (lambda (z d)
      (if
        (less? 0 d)
        (let
          ((za-k (repeated-halving d (/ z 2) 0)))
          (tangent-to-cosine-and-sine
            (double-angle-identity
              (pade (first za-k))
              (second za-k))))
        (throw (quote error) "d must be bigger than 0")))))


Quellen
http://math.stackexchange.com/questions/97560/numerically-efficient-approximation-of-coss
http://fr.wikipedia.org/wiki/Approximant_de_Pad%C3%A9


cosine-sine.sheet.xml