Impressum · Kontakt · Hilfe
Besucher online · Mitglieder



Portal > Foren > Java > Allgemeine Java-Programmierung > Errechnung der Zahl Pi in Java
Antwort
 
Themen-Optionen
Alt 12.02.2005, 19:59   Nach oben    #1
BoneCracker
Gast
 
Beiträge: n/a
Standard Errechnung der Zahl Pi in Java

Hi,
ich habe mich heute mal dran gesetzt und ein paar Methoden geschrieben, mit welchen man in Java die Zahl Pi errechnen kann. Ich weiß, dass es Math.PI gibt, aber das ist ja langweilig ..

Hier mal das, was ich bisher gemacht habe:
Java Code:
  1. /*
  2. * Created on 12.02.2005
  3. */
  4. package pi;
  5.  
  6. /**
  7. * @author Bone
  8. */
  9. public final class Pi {
  10.     private Pi() {} // Keine Instanz erlaubt
  11.    
  12.     /**
  13.      * Eine Rechnung, welche von den alten Ägyptern
  14.      * benutzt wurde.
  15.      *
  16.      * Pi =~ (16/9)²
  17.      */
  18.     public static double agypten_pi() {
  19.         return (((double)16 / 9) * ((double)16 / 9));
  20.     }
  21.    
  22.     /**
  23.      * Eine Rechnung, welche im alten Babylon benutzt
  24.      * wurde. Sie leitet sich aus einem 12-Eck her, welches
  25.      * in einem Kreis ist.
  26.      * @see [url]http://magnet.atp.tuwien.ac.at/scholz/projects/fba/graf2.gif[/url]
  27.      */
  28.     public static double babylonien_pi() {
  29.         // Grad Zahl in Radiant umwandeln
  30.         double rad   = 2 * Math.PI / 360 * (30 / 2);
  31.         double hoehe = Math.cos(rad);
  32.         double seite = Math.sin(rad);
  33.         return 12 * seite * hoehe;
  34.     }
  35.    
  36.     /**
  37.      * Antiphon (430 v. Chr) war der Meinung, dass man
  38.      * Pi errechnen könnte, in dem man sich den Kreis
  39.      * einfach als ein Vieleck mit "unendlich" Ecken
  40.      * vorstellt.
  41.      */
  42.     public static double griechenland_pi(int dreieck_anzahl) {
  43.         int anzahl   = dreieck_anzahl;
  44.         double grad  = ((double)360 / anzahl / 2);
  45.         // Grad -> Radiant
  46.         double rad   = 2 * Math.PI / 360 * grad;
  47.         double hoehe = Math.cos(rad);
  48.         double seite = Math.sin(rad);
  49.         return anzahl * seite * hoehe;
  50.     }
  51.    
  52.     /**
  53.      * Um 510 n.Chr. gab Aryabhatiya folgende Regel zur
  54.      * Bestimmung von pi an: "Addiere 4 zu 100,
  55.      * multipliziere mit 8, und addiere 62 000.
  56.      * Das Resultat ist der ungefähre Wert des
  57.      * Umfanges eines Kreises mit dem Durchmesser 20 000."
  58.      */
  59.     public static double indien_pi() {
  60.         // sonst wird eine Ganzzahl zurückgegeben   
  61.         double vier = 4;
  62.         return ((vier + 100) * 8 + 62000) / 20000;
  63.     }
  64.    
  65.     /**
  66.      * @see [url]http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Leibniz[/url]
  67.      */
  68.     public static double leibniz_pi(int durchlauf) {
  69.         double pi   = 1;
  70.         double eins = 1;
  71.         int nenner  = 1;
  72.        
  73.         for (int i = 1; i <= durchlauf; i++) {
  74.             nenner = nenner + 2;
  75.             if ((i % 2) == 1) { // ist die Zahl gerade?
  76.                 pi = pi - (eins/nenner);
  77.             } else {
  78.                 pi = pi + (eins/nenner);
  79.             }
  80.         }
  81.        
  82.         return 4 * pi;
  83.     }
  84.    
  85.     /**
  86.      * @see [url]http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Wallis[/url]
  87.      */
  88.     public static double wallis_pi(int zahlen) {
  89.         double pi   = 1;
  90.         int zaehler = 0;
  91.         int nenner  = 0;
  92.        
  93.         for (int i = 2; i < zahlen+1; i++) { // mit 2 Anfangen
  94.             if ((i % 2) == 1) { // 0.5 er Zahl
  95.                 zaehler = new Double(((i/2)-0.5)*2).intValue()+1;
  96.                 nenner  = i;
  97.             } else {
  98.                 zaehler = i;
  99.                 nenner  = new Double(((i/2)-0.5)*2).intValue();
  100.             }
  101.             pi = pi * zaehler/nenner;
  102.         }
  103.         return pi*2;
  104.     }
  105.    
  106.     /**
  107.      * WARNING: Die nenner und zaehler werden leicht gesprengt
  108.      *  -> durchlauf darf maximal 31 sein
  109.      * @see [url]http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Machin[/url]
  110.      */
  111.     public static double machin_pi(int durchlauf) {
  112.         double pi      = 0.5;
  113.         long hilfzahl2 = 1;
  114.         long nenner2   = 1;
  115.         long zaehler   = 1;
  116.         long nenner    = 1;
  117.         int hilfzahl   = 1;
  118.         int y          = 0;
  119.        
  120.         for (int i = 1; i <= durchlauf; i++) {
  121.             y       = 1;
  122.             zaehler = 1;
  123.             nenner  = 1;
  124.             for (int a = 0; a < i; a++) {
  125.                 zaehler = zaehler * y;
  126.                 nenner  = nenner  * ++y;
  127.                 y++;
  128.             }
  129.             hilfzahl  = hilfzahl + 2;
  130.             hilfzahl2 = 1;
  131.             for (int z = 0; z < hilfzahl; z++) {
  132.                 hilfzahl2 = hilfzahl2 * 2;
  133.             }
  134.             nenner2 = hilfzahl * hilfzahl2;
  135.             pi = pi + ((double)zaehler / nenner) * ((double)1 / nenner2);
  136.         }
  137.        
  138.         return 6 * pi;
  139.     }
  140.    
  141.     /**
  142.      * @see [url]http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Euler[/url]
  143.      */
  144.     public static double euler_pi(int durchlauf) {
  145.         // TODO: implementieren
  146.         return -1;
  147.     }
  148.    
  149.     /**
  150.      * Yoshiaki Tamura und Tasumasa Kanada haben mit
  151.      * folgendem die meisten Stellen bisher von Pi
  152.      * berechnet.
  153.      */
  154.     public static double tamura_pi(int durchlauf) {
  155.         double pi = 0;
  156.         double a = 1;
  157.         double x = 1;
  158.         double b = 1 / Math.sqrt(2);
  159.         double c = 1 / 4;
  160.         double y = 0;
  161.        
  162.         for (int i = 0; i < durchlauf; i++) {
  163.             y = a;
  164.             a = (a + b) / 2;
  165.             b = Math.sqrt(b * y);
  166.             c = c - x * ((a - y) * (a - y));
  167.             x = 2 * x;
  168.         }
  169.         // TODO: Fehler - es kommt immer etwa "-33.343" heraus
  170.         return ((a + b) * (a + b)) / (4 * c);
  171.     }
  172.    
  173.     /**
  174.      * TODO: Herausfinden, wie dieser Berechnungsart heißt
  175.      */
  176.     public static double nenner_pi(int durchlauf) {
  177.         double pi  = 0;
  178.         for (int i = 1; i < durchlauf; i++) {
  179.             pi = pi + ((double)1/(i*i));
  180.         }
  181.         return Math.sqrt(pi*6);
  182.     }
  183.    
  184.     /**
  185.      * TODO: Herausfinden, wie dieser Berechnungsart heißt
  186.      */
  187.     public static double nenner2_pi(int durchlauf) {
  188.         double  pi  = 0;
  189.         int  hilfz  = 2;
  190.         long nenner = 1;
  191.        
  192.         for (int i = 0; i < durchlauf; i++) {
  193.             nenner = hilfz * ++hilfz * ++hilfz;
  194.             if ((i % 2) == 1) { // gerade Zahl?
  195.                 pi = pi - ((double)1 / nenner);
  196.             } else {
  197.                 pi = pi + ((double)1 / nenner);
  198.             }
  199.         }
  200.        
  201.         return pi * 4 + 3;
  202.     }
  203.    
  204.     /**
  205.      * Eine Monte-Carlo Methode, mit welcher man
  206.      * Pi "erschießen" kann.
  207.      */
  208.     public static double erschiesse_pi(int tropfenzahl) {
  209.         double pi = 0;
  210.         int innerhalb = 0;
  211.         int gesamt = tropfenzahl;
  212.  
  213.         while (tropfenzahl > 0) { // generiere Tropfen und addiere je nach Zugehörigkeit
  214.             double dotx = 2 * Math.random() - 1;
  215.             double doty = 2 * Math.random() - 1;
  216.  
  217.             if (Math.sqrt(dotx*dotx + doty*doty) <= 1) {
  218.                 // Punkt liegt innerhalb des Kreises
  219.                 innerhalb++;
  220.             } else {
  221.                 // Punkt liegt außerhalb des Kreises
  222.             }
  223.  
  224.             tropfenzahl--;
  225.         }
  226.  
  227.         pi = 4*(double)innerhalb/gesamt;
  228.         return pi;
  229.     }
  230. }

Die Funktion tamura_pi() funktioniert leider noch nicht.

Fallen euch noch ein paar Ideen mehr ein, wie man Pi berechnen kann oder wisst ihr, wie man diese noch etwas optimieren könnte?

EDIT: Die letze Methode ist ürigens nicht von mir... diese habe ich bei wikipedia gefunden.

Mfg
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.02.2005, 20:22   Nach oben    #2
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.619
Standard

optimieren? klar.

Java Code:
  1. Math.PI;

Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.02.2005, 20:26   Nach oben    #3
BoneCracker
Gast
 
Beiträge: n/a
Standard

Hi,
ja ist schon klar .. (habe es ja auch benutzen um die Gradzahlen und Radiant umzurechnen).

Aber diese Klasse soll eher so eine Art Ideensammlung darstellen, auf welche Arten man Pi errechnen kann.

Mfg
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.02.2005, 20:29   Nach oben    #4
mic_checker
Gast
 
Beiträge: n/a
Standard

http://www.vb-helper.com/howto_calculate_pi_series.html
http://www.netzwelt.de/lexikon/Kreis...Plouffe-Formel

Bzw. von der letzten Seite der ganze Text:
http://www.netzwelt.de/lexikon/Kreiszahl.html

Btw.

Code:
            } else {
                // Punkt liegt außerhalb des Kreises
            }
Was soll das? Lass es doch ganz weg.....
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.02.2005, 20:35   Nach oben    #5
BoneCracker
Gast
 
Beiträge: n/a
Standard

Hi,
Zitat:
Zitat von mic_checker
Was soll das? Lass es doch ganz weg.....
die letze Methode hatte ich halt 1:1 von wikipedia übernommen. Ich mache es nun weg.

Vielen Dank für die Links, würde mich noch über mehr freuen

Mfg
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 18:00   Nach oben    #6
Benutzer
 
Registriert seit: 15.02.2005
Beiträge: 33
Standard

Zitat:
Zitat von BoneCracker
Hi,
Zitat:
Zitat von mic_checker
Was soll das? Lass es doch ganz weg.....
die letze Methode hatte ich halt 1:1 von wikipedia übernommen. Ich mache es nun weg.

Vielen Dank für die Links, würde mich noch über mehr freuen

Mfg
Ich habe kürzlich einmal eine Implementation der Formel von Bailey-Borwein-Plouffe mit Hilfe von BigDecimal geschrieben. Damit kannst du in halbwegs erträglicher Zeit Pi bis auf einige wenige tausend Stellen genau berechnen.
__________________
No Sig
Entitaet ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 15.02.2005, 18:31   Nach oben    #7
Erfahrener Benutzer
 
Benutzerbild von Gottzilla
 
Registriert seit: 02.02.2005
Beiträge: 515
Standard

Warum gibst du nicht einfach die Werte eines Kreises vor (also du weißt z. B. den Flächeninhalt und den Radius) und errechnest daraus PI? Dürfte doch sehr genau sein ... *zunge-raus-streck* :badgrin:
Gottzilla ist offline