ich habe hier eine Aufgabe, welche ich überhaupt nicht verstehe und vielleicht weiß ja jemand einen Ansatz, was man da machen muss. Aufgabe: Mit Hilfe Wallis Produktes pi näherungsweise berechnen. Bei n = 6 würde das so aussehen: pi/2 = 2/12/34/34/56/56/7… und das soll man dann mit 1000000 Faktoren machen, um pi genauer auszurechnen.
Danke schon einmal im Voraus
Habe schon auf Wikipedia etc. nachgeschaut, finde aber nicht einmal einen Ansatz
Überlegen wir mal:
1000000 Schritte -> wir brauchen eine Schleife
Produkt -> wir brauchen eine Variable für das laufende Produkt
Brüche -> wir brauchen Zähler und Nenner
Zähler und Nenner ändern sich abhängig davon, ob der aktuelle Schritt gerade oder ungerade ist -> wir brauchen eine Fallunterscheidung
Also ganz einfach ein Grundgerüst wie…
int z = 0;
int n = 1;
double prod = 1;
for(int i = 0; i < 1000000; i++) {
if (i % 2 == 0) {
z = ...
n = ...
} else {
z = ...
n = ...
}
prod = prod * z / n;
}
Okay es klappt
Und am Ende musste ich noch prod *2 nehmen, da da sonst immer nur pi halbe rauskamen. Ich glaube es lag daran, dass ich die Formel nicht ganz verstanden habe. Danke dir auf jeden Fall
Du solltest bei solchen Aufgaben schrittweise vorgehen: Schleife aufschrieben, erst versuchen den Zähler hinzubekommen, dann den Nenner u.s.w. Eventuell auch auf Zettel aufmalen, was passieren soll. Nur dann “rumprobieren”, wenn du auch eine Hypothese hast, **warum **das funktionieren könnte, niemals “auf gut Glück”.
Dabei immer überprüfen, ob der Code auch das macht, was du denkst, das er macht - mit println oder noch besser mit einem Debugger - jede moderne IDE hat einen, und die Viertelstunde zur Einarbeitung hast du spätestens nach zwei, drei Aufgaben wieder heraus.
* nach John Wallis und andere (ca. 1655 n. Chr.)
*/
public static double piBerechnen(int n) {
double d = 1;
int z = 2, ne = 1;
for (int i = 1; i < n; i += 2, z += 2) {
d *= (double) z / ne * ((double) z / (ne += 2));
}
return d;
}```
``` System.out.println(Math.PI / 2);
for (int i = 0; i < 101; i++) {
System.out.printf("piBerechnen(%03d) = %s%n", i, piBerechnen(i));
}```
Evtl. i richtig setzen. Es nähert sich nicht so schnell pi an. Bei der Division geht ja von groß nach klein an 1 (2 Schritte in einer Reihe). Beweis kann ich dir nicht so genau sagen. ...
Also der Beitrag war ich. Lässt man nun die zweite Klammer weg und multipliziert erst, oder dividiert man erst, das geht direkt in den Bereich von double. …
Edit: Probiert, für kleine n ist d *= (double) z / ne * (double) z / (ne += 2); besser, für große n ist d *= (double) z / ne * ((double) z / (ne += 2)); besser. (double) z kann ja ‘hinausgezogen’ werden .
@CB
Deine Lösung ist in sofern verwirrend als das TO noch ein Anfänger ist und schon die mathematische Formel nicht ganz verstanden hat und weil man Variablen immer “sprechende Namen” gibt. “z” und “ne” sind leider bedeutungslos, “zähler” und “nenner” wie von TO genutzt schon deutlich besser. Auch kannst du dir den cast auf double sparen wenn du z und ne gleich als double und nicht umständlich als int deklarierst.
Und noch zu guter letzt : man muss nicht immer auf biegen und brechen versuchen alles in eine Zeile zu drücken, denn sowas trägt leider weder zur Lesbarkeit noch zu irgendeiner Optimierung bei.
Also echt jetzt. Ich versuche, alles möglichst einfach zu halten, verkneife mir jedes += und *=, und dann haust du dem TO so ein Trainwreck um die Ohren. Im alten Griechenland hätte sie dich als “Verderber der Jugend” den Schierlingsbecher trinken lassen…
Ja, aber dann darüber diskutieren, ob man ihn getrunken hätte… Ach, anderes gesagt, ich bin jetzt schon gewohnt, dass “keiner” mich mag. Ich möchte ja nicht verwirren, Wallis kannte ich auch noch nicht. jedenfalls wird bei solchen Sachen mancherorts immer verlangt, den Beweis dazu zuschreiben (oder wie schnell PI angenähert/Veränderung) - und dagegen ströbe ich mich. Ich bin halt nicht der schlaue Mathestudent, obwohl Mathem. überall wichtig ist. Ich frag’ jetzt nur noch was, wenn ich wirklich keinen Schimmer hab. Schönen Abend.
Es hat ja niemand gesagt das du ein Matheprofessor wärst, sondern ich hab lediglich noch mal erwähnt das TO am Anfang scheinbar Schwierigkeiten hatte die Formel zu verstehen. Es trägt dann nun mal sehr zum Verständnis bei wenn man sowas auseinander zieht und dann halt eben für etwas was man als geübter Entwickler in einen Einzeiler drücken kann in 10 Zeilen zu schreiben. Auch hat TO geschrieben das er noch Java-Anfänger ist und daher vermutlich mit “+=” oder “casting” nicht viel anfangen können wird. Also ist es für ihn halt besser am Anfang erstmal noch
{
a = a + b;
}
else
{
a = a - b;
}```
zu schreiben als
```a==5?a+=b:a-=b;```
Um mal ein noch recht simples Beispiel zu geben.
Wenn er dann soweit ist und gelernt hat wie man mit den verkürzeten Operatoren arbeitet und auch in der Lage ist Code zu verstehen der so geschrieben ist dann wird er diese Schreibweise irgendwann von selbst nutzen und man wird es auch anhand seiner Codes sehen und dann wissen : aha, das und jenes kann ich ihr/ihm zutrauen.
Und das dich keiner mag, ach komm, da bin ich ja wohl deutlich "derber" dran als du.
*** Edit ***
@TO
Bitte vermeide Cross-Postings, oder weise, wenn du es denn tust, bitte auch darauf hin :
[noparse]http://www.java-forum.org/java-basics-anfaenger-themen/163438-pi-naeherungsweise-berechnen-wallis-produkt.html[/noparse]
Grund : wird in einem Forum eine Lösung erarbeitet wird meist das andere vernachlässigt ohne einen Hinweis darauf das die Frage geklärt wurde. Außerdem ist es für andere die durch eine Suche darauf treffen dann auch möglich über den Hinweis auf das jeweils andere Forum zu gelangen um dort einen Lösungsansatz oder die Lösung zu finden.
Das ist dein Problem: du merkst gar nicht, dass du verwirrst.
Landei will dem TO helfen und macht ganz langsam die Schleife einen Term nach dem anderen - so wie es bei einer Antwort für einen Anfänger angemessen ist und so, wie der TO ja schon angefangen hatte.
Dann bringst du einfach (schlechten) Code, der bei jeder Iteration zwei Terme mit hinzunimmt (da spart man sich die Fallunterscheidung usw.). Eindeutig komplizierter, in der Situation nicht hilfreich, unpassend.
Nebenbei (Hinweis für Anfänger)
d *= (double) z / ne * ((double) z / (ne += 2));
ist absolut grausam, ich sage ja fast nie was, aber die zwei Divisionen / / ohne klare Klammerung, das würde ich einem Kollegen um die Ohren hauen
Ok, also
d == result oder res
z == zaehler (Umlaute vermeiden)
n == n
ne == nenner
Auf „Anfänger“, insofern Anfänger, achtgeben
i … == … Da kann man streiten, das ist ja eigentlich ein „anderes“ z oder n(e), berechnet, also könnte man sich eine Operation sparen…
Aber(!) neben diesem Verfahren gibt es noch viele andere Verfahren, manche früher, manche später entwickelt, wie gesagt, das fällt nicht in meinen Bereich.
Immer den Datentyp angucken und die verwendeten Operationen.
@ Sen : Warum Landei und ich das so habn: bei double ist 1 + 1 - 1 glaub ich nicht immer 1, also das erhöhen verringern, manchmal wird zugesichert, manchmal nicht.
@ TO/TE : Schreib so, wie du Spaß dran hast. Laufe nicht zur Konkurrenz. im alten JFO ist auch nicht alles rosig … war da schon Monate nicht mehr vorbei geschaut.
Edit: Methodennamen(/Bezeichnungen): calcPI getPI o.ä.
Static nur dann, wenn static sinnvoll.
Anfänger oder nicht, aber umlaute sollten generell in keinem quelltext zu finden sein koennen.
Also statt zähler lieber zaehler, oder auch direkt auf englisch, also counter
(Mal abgesehen von strings oder chars ^^)
Ich mache das zwar nicht, weil ich versuche englische Bezeichner zu verwenden, aber ich sehe das in der heutigen Zeit als kein Problem mehr an. Java ist UTF-8 kompatibel und solange man dem Buildsystem explizit den Zeichensatz mitgibt (Projektdateien der IDE, gradle maven oder ant buildfile) und in der IDE konsequent UTF-8 verwendet, funktioniert das auch einwandfrei.
Da gilt dann wieder der Grundsatz der besseren Lesbarkeit.