Forum: PC-Programmierung C Programm springt mir nicht aus meiner for-Schleife raus


von Flo D. (floflovaldo)


Lesenswert?

Hallo zusammen,

ich bin gerade dabei nach einer Aufgabenstellung ein Programm zu 
schreiben, durch das ich raus bekomme wie viele Zahlenreihen ich 
benötige um auf 3.41 zu kommen.

π = 4/1 -  4/3 +  4/5 -  4/7 + ...

Das bekomme ich aktuell schon raus, allerdings mit einem manuellen 
rausspringen aus der Schleife mit dem Break und anschließenden 
durchschauen der Ausgabe.

--> mit 119 Zeichenketten komme ich auf 3.149996.

Ist es irgendwie möglich das ich beim Wert 3.41 aus der for-Schleife 
springe?
Meine Vermutung ist das es hier einfach nicht nur die 3.41 
berücksichtigt sondern auch die hinteren Stellen abgleicht. Hab auch 
schon von 3.139999 bis 3.410000 abgefragt, hier springt er mir aber auch 
nicht raus.

Kann mir jemand vielleicht einen Tipp geben wie das Programm nur die 
3.41 beachtet? Ich hätte eben gerne noch das es so lange durchläuft bis 
zur ersten 3.41 und dann eben stehen bleibt.
1
#include <stdio.h>
2
3
int main(void) {
4
  double pi = 0;  
5
  int count = 1;
6
  double n1 = 5.0; 
7
  double n2 = 7.0; 
8
9
  pi = (4 / 1.0) - (4 / 3.0);
10
11
  for (count = 3; pi >= 3.139 || pi <= 3.141; count++) {
12
    if (count % 2 == 1 ) {                
13
      pi = pi + (4.0 / n1);
14
      n1 = n1 + 4.0;
15
    }
16
    else {
17
      pi = pi - (4.0 / n2);
18
      n2 = n2 + 4.0;
19
    }
20
    printf("%f, %d\n", pi, count);
21
    if (count == 200) break; 
22
  }
23
}

von Nop (Gast)


Lesenswert?

Flo F. schrieb:

> schreiben, durch das ich raus bekomme wie viele Zahlenreihen ich
> benötige um auf 3.41 zu kommen.

3.14 meinst Du, aber Du solltest zunächst einmal verstehen, wie 
Fließkommazahlen überhaupt funktionieren. Das sind im Prinzip Brüche zur 
Basis zwei, und viele dezimal gesehen "glatte" Brüche haben keine exakte 
Repräsentation als binäre FLießkommazahlen. So wie z.B. 1/3 auch keine 
exakte dezimale Repräsentation mit endlich vielen Ziffern hat.

Davon ausgenommen sind nur Brüche, die sich als 1/(2^n) darstellen 
lassen, also etwa 0.5, 0.25, 0.125. Und damit auch deren Summen wie etwa 
0.75 oder 0.875.

Da 0.01 keine exakte Repräsentation als Fließkommazahl hat, hat 3.41 
auch keine.

Deswegen testest Du bei Fließkommazahlen niemals auf Gleichheit, sondern 
nur auf größer/größergleich und kleiner/kleinergleich, oder auf 
Intervalle.

von Karl (Gast)


Lesenswert?

(pi >= 3.139) || (pi <= 3.141)

von karadur (Gast)


Lesenswert?

Weil dein Oder immer wahr liefert.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Flo F. schrieb:
> --> mit 119 Zeichenketten komme ich auf 3.149996.
> schon von 3.139999 bis 3.1410000 abgefragt...

Gibt es bei deiner Rechnerrei überhaupt einen Wert der innerhalb dieses 
Bereichs liegt, nicht das der "Übersprungen" wird.

pi >= 3.139 || pi <= 3.141
Das sieht auch etwas komisch aus. Dass gibt doch immer ein True, oder?

von Heiner (Gast)


Lesenswert?

Flo F. schrieb:
> Ich hätte eben gerne noch das es so lange durchläuft bis
> zur ersten 3.41 und dann eben stehen bleibt.

Dann veränderst du die Abbruchbedingung deiner Schleife:

Flo F. schrieb:
> for (count = 3; pi >= 3.139 || pi <= 3.141; count++)

Die Vergleiche müssen genau umgekehrt sein: Du willst die Iteration 
fortsetzen, bis zu im gewünschten Intervall angekommen bist. Die 
logische Verknüpfung ist dann auch anders ...


Außerdem willst du auch den Schleifenrumpf überdenken. Das geht ohne 
if/else erheblich kürzer, einfacher und logischer.

von Sebastian S. (amateur)


Lesenswert?

Würde ich auch nicht machen!
Dank ODER ist es da so schön drinnen.

von Theor (Gast)


Lesenswert?

Mit allem Respekt: Das ist ja ein furchtbar unverständliches 
Geschreibsel.

Natürlich kann man erkennen, dass es um eine Variante der Leibnizschen 
Näherung von Pi geht.
Offenbar geht es auch darum, eine Abbruchbedingung für die Schleife 
festzulegen.

OK. Aber nun schreibe mal bitte die Aufgabenstellung hin. Dann wird 
vielleicht klar, wo es hingehen soll.
Vermutlich ist der Kern der Aufgabe die Abbruchbedingung festzulegen und 
zu begründen. Sagt Dir das Wort "Konvergenz" aus dem Matheunterricht 
noch was? Was ist das?

von Flo (Gast)


Lesenswert?

Die Aufgabe ist nur ein Programm zur Berechnung der Kreiszahl pi mit der 
Leibnizschen Nährung zu erstellen.
Die Frage lautet wie viele Reihenglieder werden benötigt, hier komme ich 
eben auf die 119.

von Theor (Gast)


Lesenswert?

Na schön, Flo. Die Aufgabe ist leider fehlerhaft beschrieben, Deine 
Annahme unbegründet, aber lassen wir das mal.


Ich rate Dir dazu, ganz genau zu überlegen, für welche Zahlenbereich die 
Bedingung in Deiner for-Schleife wahr oder falsch ist.

Weiter rate ich Dir noch einmal im C-Buch nachzuschauen, was diese 
Bedingung genau bewirkt.

Dann rate ich Dir, noch genau zu überlegen, welche zwei Zahlen, gemäß 
der Aufgabenstellung die Zahl Pi "umgeben". Welche Rolle genau spielt 
dabei die Anzahl der Stellen.

Abschliessend rate ich Dir, Dich mit der Darstellung von 
Fliesskommazahlen im Computer noch einmal gründlich zu befassen. Welche 
Zahlen kann man genau und welche nur mit einem gewissen Fehler 
darstellen?

von Trick aus dem Netz (Gast)


Lesenswert?

ich habe im Netz einen Trick gesehen wie man Fließkommazahlen auf x 
Stellen rundet:
1
gerundete_zahl=(int)(fliesskommazahl*100+0.5)/100.0; //runden auf 2 Stellen
Mit diesem Ansatz komme ich auf 153 Durchläufe:
1
   double pi_double = 0.0;
2
   int pi_int = 0;
3
4
   double num = 4.0; // numerator
5
   int den; // denominator
6
7
   int i;
8
   for (i = 1, den = 1; pi_int != 314; i++, den += 2) {
9
      pi_double += num / den;
10
      pi_int = (int)(pi_double * 100 + 0.5);
11
12
      printf("round(%f)=%f\n", pi_double, pi_int / 100.0);
13
14
      num *= -1;
15
   }
16
   printf("\nIterationen: i=%d\n", i);

von Trick aus dem Netz (Gast)


Lesenswert?

Aber es gibt ja auch noch die round()-Funktion....

von Trick (Gast)


Lesenswert?

mit round():
1
...
2
pi_int = (int)round(pi_double * 100);
3
...

von Trick (Gast)


Lesenswert?

Trick aus dem Netz schrieb:
> Mit diesem Ansatz komme ich auf 153 Durchläufe

152 ;-) Die letzte Inkrementierung sollte man ja  nicht dazuzählen.

von ohne Tricks (Gast)


Lesenswert?

ganze ohne Tricks. Auch 152 Durchläufe.
1
   double my_pi = 0.0;
2
   double num = 4.0; // numerator
3
4
   // num= denominator
5
   for (int i = 1, den = 1; my_pi < 3.135 || my_pi > 3.144;
6
        i++, den += 2) {
7
      my_pi += num / den;
8
      printf("%d: %f\n", i, my_pi);
9
      num *= -1;
10
   }

von musst du nicht runden? (Gast)


Lesenswert?

Flo F. schrieb:
> --> mit 119 Zeichenketten komme ich auf 3.149996.

Und das ist doch 3.15 aufgerundet.

von Dirk K. (merciless)


Lesenswert?

IMHO ist es besser, die Abweichung zu berechnen
und abzubrechen, wenn diese klein genug ist.
1
for (count = 3; fabs(pi - 3.14) > 0.001; count++) {

merciless

von Mark B. (markbrandis)


Lesenswert?

Flo F. schrieb:
>   for (count = 3; pi >= 3.139 || pi <= 3.141; count++)

Das ist eine Endlosschleife. Egal welchen Wert pi hat, die Bedingung "pi 
ist größer gleich 3.139 ODER pi ist kleiner gleich 3.141" ist immer 
erfüllt.

Natürlich kann man auch aus einer Endlosschleife herausspringen. Die 
elegantere Lösung wäre freilich, sich die Abbruchbedingung für die 
Schleife so zu überlegen, dass sie eben nicht endlos läuft.

: Bearbeitet durch User
von Planlos (Gast)


Lesenswert?

Mark B. schrieb:
> pi ist kleiner gleich 3.141

Pi ist weder kleiner noch gleich 3.141, da Pi, wenn ich mich recht 
entsinne, 3.14159..... ist. Sollte man da nicht eher einen Wert nehmen, 
der tatsächlich größer als Pi ist, damit Pi dann auch ne Chance hat, 
überhaupt kleiner zu sein als der Vergleichswert?

von Mark B. (markbrandis)


Lesenswert?

Planlos schrieb:
> Pi ist weder kleiner noch gleich 3.141

Das ist mir schon klar. Ich bezog mich auch nicht auf die transzendente 
Zahl Pi, sondern auf die Verwendung der Variable pi im Code des 
Themenerstellers. Dessen Vergleich so halt keinen Sinn ergibt. ;-)

: Bearbeitet durch User
von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

schau mal hier:
https://www.ict4us.com/r.kuijt/de_pi.htm
also:
const float pi = 3.14;

und warum ist bei Dir:
pi = (4 / 1.0) - (4 / 3.0);

Ist bei Dir pi am Ende eine ganz andere Konstante als die Kreiszahl pi 
gemeint ?
Könnte ja sein!

Woher hast Du nur das copy&paste Programm :-))

: Bearbeitet durch User
von sid (Gast)


Lesenswert?

Robert K. schrieb:
> und warum ist bei Dir:
> pi = (4 / 1.0) - (4 / 3.0);
>
> Ist bei Dir pi am Ende eine ganz andere Konstante als die Kreiszahl

na komm, dass er das als Startwert nutzt um sich hoffentlich immer 
weiter Pi anzunähern ist ja schon doch sehr offensichtlich, oder nicht?

'sid

von S. R. (svenska)


Lesenswert?

Wie wäre es mit:
1
if (fabs(pi - 3.14) < 0.01)
2
  break;

?

von Rolf M. (rmagnus)


Lesenswert?


von Pi-ter (Gast)


Lesenswert?

Unabhängig von deiner Lösung frage ich mich warum man iteriert wenn man 
das Endergebnis schon kennt. Ich würde erwarten, dass man bei 
Unterschreiten eines Schwellwertes für die Änderung abbricht.

von Pandur S. (jetztnicht)


Lesenswert?

Die Aenderung als Abbruchkriterium ? Dann kann mich sich das gleich 
alles schenken :

Aenderung = 4/N

N= 4/Aenderung !

Fertig

von irgendwelche Reihen (Gast)


Lesenswert?

Pi-ter schrieb:
> Unabhängig von deiner Lösung frage ich mich warum man iteriert wenn man
> das Endergebnis schon kennt.

Gibt es in jedem Buch als Übungsaufgabe.

von Joachim B. (jar)


Lesenswert?

Flo D. schrieb:
> Hallo zusammen,

Flo schrieb:
> Die Aufgabe ist nur ein Programm

1. 2 Namen schon mal ungünstig!

Theor schrieb:
> Na schön, Flo. Die Aufgabe ist leider fehlerhaft beschrieben, Deine
> Annahme unbegründet, aber lassen wir das mal.

warum lassen?

es muss doch mal deutlich gesagt werden das man normalerweise nicht aus 
Schleifen springt, die sollen beendet werden wenn die Bedingung erfüllt 
ist!

der Titel ist schon denkbar unglücklich!
C-Buch und lernen ist die erste Pflicht vor sinnlosem C&P

abgesehen davon sehe ich nur 2 Posting vom TO, der hat sich 
offensichtlich längst verabschiedet, manche wollen solche Antworten halt 
nicht hören oder lesen, sie wollen "nur" Lösungen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.