# PI mit Algorithmus berechnen



## Youssarian (5. Dez 2012)

Hallo zusammen,

derzeit versuche ich mich an einem Programm bei dem ein Algorithmus programmiert werden muss und da häng ich grade. Wäre über ein paar Denkanstöße /Hilfestellungen sehr dankbar, da ich noch sehr neu in der Welt des Programmierens bin.

Zur Aufgabenstellung:
-mit n Zufallspunkten soll die Zahl PI berechnet werden
- x und y- Koordinate sollen mit „Math.random()“ berechnet werden
-bei n > 0 soll die Zahl PI ermittelt werden
-bei n < 0 soll der Algorithmus solange laufen bis der berechnete Wert von PI um nicht mehr als +-0,001 abweicht und die dafür benötigte Anzahl der Zufallspunkte soll ausgegeben werden.

Meine ersten Versuche:
-Meine erste Überlegung war 4* PunkteimKreis / Zufallspunkte, aber so bekomm ich ein PI von max 0,3 raus.
-für den Algorithmus habe ich nicht mal einen wirklichen Ansatz. Habe es bereits mit 
while (n <0 && 3,139 <PI && PI < 3.141)
versucht, aber das funktioniert vorne und hinten nicht.
Gibt es vielleicht eine Grundstruktur für Algorithmen, die solange laufen bis eine Zahl auf einen bestimmten Wert genau ausgerechnet wurde? 

Über ein paar Hilfestellungen wäre ich euch unendlich dankbar.

Gruß


----------



## D4rkscr43m (5. Dez 2012)

Youssarian hat gesagt.:


> while (n <0 && 3,139 <PI && PI < 3.141)



Ist zumindest der richtige Ansatz für eine "Lauf solange wie [...]"-Schleife, werf aber mal das n < 0 raus (wenn n für die Anzahl der Punkte steht, da wirst du ja mit 0 anfangen und somit ist das sofort false)
Danach nehmen wir mal 3*.*139*5* < PI ... das heißt, deine Schleife läuft SOLANGE WIE dein PI größer ist als dieser Wert. Du willst deine Schleife aber laufen lassen, wenn der Wert von PI NICHT größer ist als deine Vorgabe. Also entweder mit ! negieren oder das kleiner Zeichen zu einem größer Zeichen machen. Beim PI < 3.14*25* genau so.

Mal kurz zu den Anpassungen der Zahlen. Der Punkt ist in Java das Dezimaltrennzeichen.
Dann soll dein Ergebnis von 3,1415 nicht mehr als 0,001 abweichen. Obergrenze ist damit 3,1425 (+0,001) und Untergrenze ist 3,1395 (-0,001)

Wenn du dann noch Probleme hast, kannst du ja mal deinen ganzen Algorithmus posten. Verwende dann aber am besten die [JAVA]-Tags


----------



## SlaterB (5. Dez 2012)

> while (n <0 && 3,139 <PI && PI < 3.141)
> versucht, aber das funktioniert vorne und hinten nicht.

tja, fsöljtglkwejlekwjlkjtlkjsdls geht auch links und rechts nicht,
wenn du nicht mit Worten einen Sinn erklären kannst, ist oftmals keiner da,

> -Meine erste Überlegung war 4* PunkteimKreis / Zufallspunkte, aber so bekomm ich ein PI von max 0,3 raus.
hier ist der richtige Ansatz für den Algorithmus schon genannt, ob bewußt oder zufällig,

> - x und y- Koordinate sollen mit „Math.random()“ berechnet werden
ist ja auch ein recht deutlicher Verweis auf ein bestimmtes Verfahren:

du sollst einen Zufallspunkt bestimmen und prüfen ob der innerhalb oder außerhalb eines Kreises liegt, was mit Radius-Bestimmung leicht geht, das Ganze n-mal, die Schleife läuft einfach bis n und fertig, 
bzw. ewig weiter bis der berechnete Wert nahe an PI liegt, das ist vielleicht das was du mit deinem while versucht hast,
aber nicht alles auf einmal, festes n reicht als 1. Variante

anhang einer Skizze der Flächen kann man sich anschauen was in etwa rauskommen dürfte, wie groß welche Fläche ist,
warum du 0.3 hast kann ohne Erklärungen/ Code nicht beurteilt werden

denke selber weiter und schreibe Fragen dazu oder poste Code, dann kann man weiteres besprechen


----------



## Youssarian (5. Dez 2012)

Nabend,

erstmal vielen Dank für die Antworten.

Ich hab mich mal an dem ganzen versucht und hier das Ergebnis. Leider läuft es noch lange nicht so wie gewünscht. Hoffentlich habe ich da keine groben Fehler drin.


```
import java.io.*; //Wichtig, in jedem Programm einfügen!!!
import java.text.*; //Wichtig, in jedem Programm einfügen!!!
import java.util.Random; //Wichtig, in jedem Programm einfügen!!!
public class PI
{
    public static void main( String args[] ) {
        ABC fenster = new ABC("PI");

        boolean programmEnde = false ;
        boolean bedingungNichtOk;
        double xi, yi, z, r, PI; 
        long n ;
        xi = Math.random();
        yi = Math.random();
        try{
            while (true) {
                do{
                    fenster.println("Geben Sie die Anzahl n der Zufallspunkte Pi ein. Hinweis: Bei n=0 wird das Programm beendet!");
                    n = fenster.readLong("Geben Sie n ein: ");
                    if (n == 0) {
                        fenster.println("Programmende wirklich erwünscht?");
                        n = fenster.readLong("Ja = 1:  ");
                        if (n == 1) {
                        fenster.println("Programmende");
                        programmEnde = true;
                        break; 
                    }
                       else {
                        bedingungNichtOk = false; 
                    }
                }
                    else {
                        bedingungNichtOk = false; 
                    }
                if (n > 0) {
                         z = (Math.pow((xi-0.5),2)) + (Math.pow((yi-0.5),2));
                         PI = 4*z/n;
                         System.out.println(" PI =" +PI);
                         System.out.println(" n =" +n);
                    }
                    else {
                        bedingungNichtOk = false; 
                    }
                if (n < 0) {
                    do{ 
                        z = (Math.pow((xi-0.5),2)) + (Math.pow((yi-0.5),2));
                        PI = 4*z/n;
                        System.out.println(" PI =" +PI);
                        System.out.println(" n =" +n);
                    }while (3.14059 < PI && PI < 3.14259);
                }
                    else {
                        bedingungNichtOk = false; 
                    }
                }while (bedingungNichtOk);
                if (programmEnde) {
                    break;
                }
            }
        }
        catch (InterruptedException ie) {}
    }
}
```

Gruß und danke


----------



## Bernd Hohmann (5. Dez 2012)

Guck mal hier: https://de.wikipedia.org/wiki/Kreiszahl#Statistische_Bestimmung

Die Genauigkeit für die Abbruchbedingung ermittelst Du, in dem Du von Math.PI deinen aktuellen Wert abziehst, den Absolutbetrag ermittelst (Math.abs glaube ich) und der muss kleiner als 0,001 sein.

Bernd


----------



## SlaterB (5. Dez 2012)

> Hoffentlich habe ich da keine groben Fehler drin.

ja was du denn da drin? wenn du das nicht mit Worten beschreiben, den Sinn/ das Ziel, den Weg dahin skizzieren,
mit Papier und paar pseude-zufälligen Werten nachrechnen kannst, dann ist das ein größeres Problem als du im Code je haben kannst


```
do{ 
                        z = (Math.pow((xi-0.5),2)) + (Math.pow((yi-0.5),2));
                        PI = 4*z/n;
                        System.out.println(" PI =" +PI);
                        System.out.println(" n =" +n);
                    }while (3.14059 < PI && PI < 3.14259);
```
ungeachtet ob korrekt programmiert oder nicht rechnest du immer nur einen Wert aus,
das ist nicht das Ziel der Aufgabe, siehe geposteten Link

im Bereich Zeile 20 bis 34 im besonderen und allgemein ist deine Einrückung ziemlich kritisch,
darauf musst du unbedingt achten, 
Klammer auf und zu, eingerückter Code, soll was aussagen, was in welchem if oder Schleifenblock steht


----------



## pappawinni (5. Dez 2012)

Hatten wir das nicht erst kürzlich..
http://www.java-forum.org/java-basics-anfaenger-themen/144280-frage-bez-schleife.html#post961997


----------



## pappawinni (6. Dez 2012)

Was Bernd vorschlägt wäre dann wohl etwa sowas:


```
double pi = 0;
        int innerhalb = 0;
        int gesamt=0;
       
        do { // generiere Tropfen und addiere je nach Zugehörigkeit
          double dotx = Math.random();
          double doty = Math.random();
       
          if (dotx*dotx + doty*doty <= 1) {
            // Punkt liegt innerhalb des Kreises
            innerhalb++;
          } else {
            // Punkt liegt außerhalb des Kreises
          }
       
          gesamt++;
          pi = 4*(double)innerhalb/gesamt;
          System.out.printf("Nach %d Iterationen ist pi %f%n",gesamt,pi);
        } while (Math.abs(pi-Math.PI)>0.001);
```


----------



## Youssarian (6. Dez 2012)

Wow, das funktioniert ja fast schon genau so wie es soll. Fehlt zwar noch die untere Grenze für Pi, aber hoffentlich bekomm ich das noch alleine hin.

Ich danke euch vielmals für die große Hilfe und entschuldigt, dass ich zwischenzeitig so rumgetrollt habe.

Gruß


----------



## Bernd Hohmann (6. Dez 2012)

Youssarian hat gesagt.:


> Fehlt zwar noch die untere Grenze für Pi, [...]



Welche untere Grenze? Meinst Du den Vergleich auf > 0.001 ? Da wird vorher der Absolutwert gebildet sodass die Zwangsjacke schon gut passt.

Bernd


----------



## Youssarian (6. Dez 2012)

Stimmt, da war ich wohl etwas zu schnell mit dem tippen.

Das Programm spuckt aber leider immer noch nicht exakt die Werte aus, die uns unser Lehrer vorgegeben hat. 
Kann man überhaupt immer die selben Werte erhalten? Schließlich handelt es sich hier um ein Zufallsexperiment.

Gruß


----------



## Bernd Hohmann (6. Dez 2012)

Youssarian hat gesagt.:


> Das Programm spuckt aber leider immer noch nicht exakt die Werte aus, die uns unser Lehrer vorgegeben hat.  Kann man überhaupt immer die selben Werte erhalten? Schließlich handelt es sich hier um ein Zufallsexperiment.



Eben.

Ich habs (danke an papa winnie für den Source) eben mal ausprobiert: je nach Lust und Laune des Zufallsgenerators hab ich ein Ergebnis in 200 oder erst in 5000 Schritten. Das Ergebnis variiert auch, ist aber innerhalb der vorgegebenen Grenze von 0,001

Bernd


----------



## Youssarian (6. Dez 2012)

Dann funktioniert es ja einwandfrei. Ich danke vielmals


----------

