StartseitePi berechnenNoch mehr Nachkommastellen

Noch mehr Nachkommastellen

Wer deutlich mehr Nachkommastellen benötigt, kommt nicht darum herum, einen besseren Algorithmus als den auf den vorherigen Seiten hergeleiteten zu benutzen, denn dieser lässt sich nicht wirklich effizient implementieren. Insbesondere das Wurzelziehen benötigt bei zunehmender Genauigkeit deutlich mehr Rechenleistung. Zum Beispiel eignet sich der 1770 von Johann Heinrich Lambert publizierte Kettenbruch, da er leicht mit einfachen arithmetischen Operationen implementiert werden kann:

\frac{4}{\pi}=1+\frac{1^2}{3+\frac{2^2}{5+\frac{3^2}{7+\frac{4^2}{9+\frac{5^2}{\ddots}}}}}

Laut Wikipedia bringt jeder Schritt etwa 0,76555 Dezimalstellen. Ich habe diesen Algorithmus in der funktionalen Programmiersprache Haskell implementiert und bin davon ausgegangen, dass jeder Schritt 0,75 Dezimalstellen bringt. Außerdem sollten – um sicher zu gehen – erst mal zehn Schritte für die erste Dezimalstelle gemacht werden, damit die Stellen auch mit Sicherheit stimmen:

  1. module Pi (approximate) where

  2. import ShowRational

  3. -- Berechnet Pi mindestens auf n Stellen genau
  4. approximate :: Integer -> Rational
  5. approximate n = 4 / (lambert 1 steps)
  6.   where steps = floor (4/3*(fromInteger n) + 10)

  7. -- Berechnet den Lambertkettenbruch bis ins nte Glied
  8. lambert :: Integer -> Integer -> Rational
  9. lambert k n | (k == n) = 1
  10.   | otherwise = a + b / (lambert (k+1) n)
  11.   where a = fromInteger (2*k-1)
  12.   b = fromInteger (k^2)

Folgendes Modul ist nur für die Gleitkomma-Ausgabe rationaler Zahlen (die in Haskell als gekürzter Bruch dargestellt werden) nötig (gerundet wird nicht):

  1. module ShowRational (showRational) where

  2. -- Wandelt r mit n Nachkommastellen in eine Zeichenkette um
  3. showRational :: Integer -> Rational -> String
  4. showRational n r = (show intDigits) ++ "." ++ (showFracs n fracDigits)
  5.   where intDigits = truncate r
  6.   fracDigits = 10 * (r-(fromInteger intDigits))

  7. -- Wandelt die ersten n Nachkommastellen in eine Zeichenkette
  8. showFracs :: Integer -> Rational -> String
  9. showFracs 0 r = ""
  10. showFracs n r = (show first) ++ (showFracs (n-1) rest)
  11.   where first = truncate r
  12.   rest = 10 * (r - (fromInteger first))

Zum Beispiel mit dem Aufruf

showRational 100 (approximate 100)

berechnet dieses Programm Pi auf 100 Nachkommastellen genau und gibt das Ergebnis dann auch auf 100 Nachkommastellen genau aus. Auf meinem Laptop (CPU: AMD Turion™ 64 X2 TL-50 @ 1,6 GHz (Dual-Core) mit dem Haskell-Interpreter Hugs, wobei nur einer der beiden Prozessoren genutzt wurde) benötigte dieser Algorithmus ohne die Gleitkomma-Umwandlung (also nur der Aufruf "approximate 1000") knapp 4:30 Minuten, um Pi auf 1000 Nachkommastellen genau zu berechnen: Ergebnis (mit Gleitkomma-Umwandlung).

Ausblenden