B
BoneCracker
Mitglied
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 .. Very Happy
Hier mal das, was ich bisher gemacht habe:
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?
Die letze Methode ist ürigens nicht von mir... diese habe ich bei wikipedia gefunden.
Mfg
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 .. Very Happy
Hier mal das, was ich bisher gemacht habe:
Code:
/*
* Created on 12.02.2005
*/
package pi;
/**
* @author Bone
*/
public final class Pi {
private Pi() {} // Keine Instanz erlaubt
/**
* Eine Rechnung, welche von den alten Ägyptern
* benutzt wurde.
*
* Pi =~ (16/9)²
*/
public static double agypten_pi() {
return (((double)16 / 9) * ((double)16 / 9));
}
/**
* Eine Rechnung, welche im alten Babylon benutzt
* wurde. Sie leitet sich aus einem 12-Eck her, welches
* in einem Kreis ist.
* @see http://magnet.atp.tuwien.ac.at/scholz/projects/fba/graf2.gif
*/
public static double babylonien_pi() {
// Grad Zahl in Radiant umwandeln
double rad = 2 * Math.PI / 360 * (30 / 2);
double hoehe = Math.cos(rad);
double seite = Math.sin(rad);
return 12 * seite * hoehe;
}
/**
* Antiphon (430 v. Chr) war der Meinung, dass man
* Pi errechnen könnte, in dem man sich den Kreis
* einfach als ein Vieleck mit "unendlich" Ecken
* vorstellt.
*/
public static double griechenland_pi(int dreieck_anzahl) {
int anzahl = dreieck_anzahl;
double grad = ((double)360 / anzahl / 2);
// Grad -> Radiant
double rad = 2 * Math.PI / 360 * grad;
double hoehe = Math.cos(rad);
double seite = Math.sin(rad);
return anzahl * seite * hoehe;
}
/**
* Um 510 n.Chr. gab Aryabhatiya folgende Regel zur
* Bestimmung von pi an: "Addiere 4 zu 100,
* multipliziere mit 8, und addiere 62 000.
* Das Resultat ist der ungefähre Wert des
* Umfanges eines Kreises mit dem Durchmesser 20 000."
*/
public static double indien_pi() {
// sonst wird eine Ganzzahl zurückgegeben
double vier = 4;
return ((vier + 100) * 8 + 62000) / 20000;
}
/**
* @see http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Leibniz
*/
public static double leibniz_pi(int durchlauf) {
double pi = 1;
double eins = 1;
int nenner = 1;
for (int i = 1; i <= durchlauf; i++) {
nenner = nenner + 2;
if ((i % 2) == 1) { // ist die Zahl gerade?
pi = pi - (eins/nenner);
} else {
pi = pi + (eins/nenner);
}
}
return 4 * pi;
}
/**
* @see http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Wallis
*/
public static double wallis_pi(int zahlen) {
double pi = 1;
int zaehler = 0;
int nenner = 0;
for (int i = 2; i < zahlen+1; i++) { // mit 2 Anfangen
if ((i % 2) == 1) { // 0.5 er Zahl
zaehler = new Double(((i/2)-0.5)*2).intValue()+1;
nenner = i;
} else {
zaehler = i;
nenner = new Double(((i/2)-0.5)*2).intValue();
}
pi = pi * zaehler/nenner;
}
return pi*2;
}
/**
* WARNING: Die nenner und zaehler werden leicht gesprengt
* -> durchlauf darf maximal 31 sein
* @see http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Machin
*/
public static double machin_pi(int durchlauf) {
double pi = 0.5;
long hilfzahl2 = 1;
long nenner2 = 1;
long zaehler = 1;
long nenner = 1;
int hilfzahl = 1;
int y = 0;
for (int i = 1; i <= durchlauf; i++) {
y = 1;
zaehler = 1;
nenner = 1;
for (int a = 0; a < i; a++) {
zaehler = zaehler * y;
nenner = nenner * ++y;
y++;
}
hilfzahl = hilfzahl + 2;
hilfzahl2 = 1;
for (int z = 0; z < hilfzahl; z++) {
hilfzahl2 = hilfzahl2 * 2;
}
nenner2 = hilfzahl * hilfzahl2;
pi = pi + ((double)zaehler / nenner) * ((double)1 / nenner2);
}
return 6 * pi;
}
/**
* @see http://magnet.atp.tuwien.ac.at/scholz/projects/fba/fba.html#sec_Euler
*/
public static double euler_pi(int durchlauf) {
// TODO: implementieren
return -1;
}
/**
* Yoshiaki Tamura und Tasumasa Kanada haben mit
* folgendem die meisten Stellen bisher von Pi
* berechnet.
*/
public static double tamura_pi(int durchlauf) {
double pi = 0;
double a = 1;
double x = 1;
double b = 1 / Math.sqrt(2);
double c = 1 / 4;
double y = 0;
for (int i = 0; i < durchlauf; i++) {
y = a;
a = (a + b) / 2;
b = Math.sqrt(b * y);
c = c - x * ((a - y) * (a - y));
x = 2 * x;
}
// TODO: Fehler - es kommt immer etwa "-33.343" heraus
return ((a + b) * (a + b)) / (4 * c);
}
/**
* TODO: Herausfinden, wie dieser Berechnungsart heißt
*/
public static double nenner_pi(int durchlauf) {
double pi = 0;
for (int i = 1; i < durchlauf; i++) {
pi = pi + ((double)1/(i*i));
}
return Math.sqrt(pi*6);
}
/**
* TODO: Herausfinden, wie dieser Berechnungsart heißt
*/
public static double nenner2_pi(int durchlauf) {
double pi = 0;
int hilfz = 2;
long nenner = 1;
for (int i = 0; i < durchlauf; i++) {
nenner = hilfz * ++hilfz * ++hilfz;
if ((i % 2) == 1) { // gerade Zahl?
pi = pi - ((double)1 / nenner);
} else {
pi = pi + ((double)1 / nenner);
}
}
return pi * 4 + 3;
}
/**
* Eine Monte-Carlo Methode, mit welcher man
* Pi "erschießen" kann.
*/
public static double erschiesse_pi(int tropfenzahl) {
double pi = 0;
int innerhalb = 0;
int gesamt = tropfenzahl;
while (tropfenzahl > 0) { // generiere Tropfen und addiere je nach Zugehörigkeit
double dotx = 2 * Math.random() - 1;
double doty = 2 * Math.random() - 1;
if (Math.sqrt(dotx*dotx + doty*doty) <= 1) {
// Punkt liegt innerhalb des Kreises
innerhalb++;
} else {
// Punkt liegt außerhalb des Kreises
}
tropfenzahl--;
}
pi = 4*(double)innerhalb/gesamt;
return pi;
}
}
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?
Die letze Methode ist ürigens nicht von mir... diese habe ich bei wikipedia gefunden.
Mfg