Frage

Ich mache andere C ++ Übung. Ich habe den Wert von pi aus der unendlichen Reihe zu berechnen:

pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 -4/11 +. . .

Das Programm hat den ungefähren Wert von Pi nach jedem der ersten 1.000 Bedingungen dieser Serie zu drucken. Hier ist mein Code:

#include <iostream>
using namespace std;

int main()
{
    double pi=0.0;
    int counter=1;

    for (int i=1;;i+=2)//infinite loop, should "break" when pi=3.14159
    {
        double a=4.0;
        double b=0.0;

        b=a/static_cast<double>(i);

        if(counter%2==0)
            pi-=b;
        else
            pi+=b;

        if(i%1000==0)//should print pi value after 1000 terms,but it doesn't  
            cout<<pi<<endl;

        if(pi==3.14159)//this if statement doesn't work as well
            break;

        counter++;
    }

    return 0;
}

Es kompiliert ohne Fehler und Warnungen, sondern nur das leere Konsolenfenster erscheint nach der Ausführung. Wenn ich Zeile entfernen“, wenn (i% 1000 == 0)“, kann ich sehen, es läuft und Druck jeden pi Wert, aber es hört nicht auf, was die zweite bedeutet if-Anweisung funktioniert auch nicht. Ich bin mir nicht sicher, was anderes zu tun. Ich nehme an, es ist wahrscheinlich ein einfacher logischen Fehler.

War es hilfreich?

Lösung

Nun, i% 1000 wird nie = 0, als Zähler läuft von i = 1, dann in Schritten von 2. Daher i ist immer ungerade, und wird nie ein Vielfaches von 1000 sein.

Der Grund, es endet nie ist, dass der Algorithmus nicht genau konvergiert 3,14157 - es wird eine höhere Präzision entweder unter oder über Annäherung. Sie wollen sagen: „Wenn innerhalb eines gegebenen Delta von 3,14157“, so schreiben

if (fabs(pi - 3.14157) < 0.001)
  break

oder etwas ähnliches, denn wie „schließen“ Sie erhalten möchten, bevor Sie stoppen.

Andere Tipps

Da Sie i auf 1 und Zuwachs von 2 beginnen, i ist immer eine ungerade Zahl ist, so dass ich% 1000 wird nie 0 sein.

Sie haben mehr als ein Problem:

A. i% 1000 == 0 wird nie wahr sein, weil Sie nur ungerade Zahlen iterieren.

B. pi == 3,14159: Sie können keine doppelten Werte vergleichen nur so, weil die Art und Weise Gleitkommazahlen dargestellt (man darüber hier in einer anderen Frage lesen kann). um es Ihnen zu arbeiten, sollen die Werte in einer anderen Art und Weise zu vergleichen, -. ein Weg ist, um sie voneinander zu subtrahieren und prüfen, ob das absolute Ergebnis niedriger als 0.0000001

  1. Sie haben Gleitkommagenauigkeit Fragen. Versuchen Sie if(abs(pi - 3.14159) < 0.000005).
  2. i%1000 nie 0 sein, weil i immer ungerade ist.

Sollte es nicht sein:

if (counter%1000==0)
  1. i bei 1 beginnt und erhöht sich dann um 2. Daher ist i immer ungerade und wird nie ein Vielfaches von 1000 sein, was, warum, wenn (i% 1000 == 0) ist nie passiert.

  2. Direkt Schwimmer Vergleich nicht funktioniert, aufgrund Schwimm Präzision Probleme. Sie müssen vergleichen, dass die Differenz zwischen den Werten nahe genug ist.

pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 -4/11 + ...

verallgemeinern

pi = Σ i = 0 (1) i 4 / (2 i 1)

Welche uns einen sauberere Ansatz gibt jeden Begriff; das i 'th Begriff ist gegeben durch:

double term = pow(-1,i%2) * 4 / (2*i+1);

Dabei steht i = 0,1,2, ..., N

So können unsere Schleife ziemlich einfach sein, da eine gewisse Anzahl von Iterationen N

int N=2000;
double pi=0;
for(int i=0; i<N; i++)
{
    double term = pow(-1,i%2) * 4 / (2*(double)i+1);
    pi += term;
    cout << i << "\t" << pi <<endl;
}

Ihre ursprüngliche Frage, erklärte: „Das Programm hat den ungefähren Wert von Pi nach jedem der ersten 1.000 Bedingungen dieser Serie drucken“. Dies bedeutet nicht, keine Notwendigkeit zu prüfen, ob 3,14159 erreicht ist, so habe ich das nicht hier eingeschlossen. Der pow(-1,i%2) Aufruf ist nur if Aussagen (die langsam sind) und verhindert, dass Komplikationen mit großen i .

zu vermeiden

Beachten Sie, dass nach einer bestimmten Anzahl von Iterationen, die Differenz zwischen der Größe der Zahl Pi und der Größe der Korrekturterm (sagen wir -4/25) so klein sein, dass sie über die Präzision eines double gehen, so dass Sie müssen höhere Präzision Typen würde damit umgehen.

In der Standardeinstellung abs verwendet den abs Makro, das für int ist. Für Doppel, verwenden Sie die cmath Bibliothek.

#include <iostream>
#include <cmath>

int main()
{
    double pi=0.0;

    double a=4.0;
    int i = 1; 

    for (i=1;;i+=2)
    {

        pi += (1 - 2 * ((i/2)%2)) * a/static_cast<double>(i);          

        if( std::abs(pi - 3.14159) < 0.000001 )
              break;

        if (i > 2000) //1k iterations
              break;
    }

    std::cout<<pi<<std::endl;

    return 0;
}

Hier ist der korrigierte Code. Ich dachte, es in der Zukunft nützlich sein kann, wenn jemand ähnliches Problem hat.

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
double pi=0.0;
int counter=1;

for (int i=1;;i+=2)
{
 double a=4.0;
 double b=0.0;

 b=a/static_cast<double>(i);

 if(counter%2==0)
  pi-=b;
 else
  pi+=b;

 if(counter%1000==0) 
  cout<<pi<<" "<<counter<<endl;


 if (fabs(pi - 3.14159) < 0.000001) 
  break;

 counter++;
}
cout<<pi;

 return 0;
}

Hier ist ein besserer:

class pi_1000
{
public:
    double doLeibniz( int i ) // Leibniz famous formula for pi, source: Calculus II :)
    {
        return ( ( pow( -1, i ) ) * 4 ) / ( ( 2 * i ) + 1 );
    }

 void piCalc()
{
    double pi = 4;
    int i;

    cout << "\npi calculated each iteration from 1 to 1000\n"; //wording was a bit confusing.
                                                    //I wasn't sure which one is the right one: 0-1000 or each 1000th.
    for( i = 1; i < 1000; i++ )
    {
        pi = pi + doLeibniz( i );
        cout << fixed << setprecision( 5 ) << pi << "\t" << i + 1 << "\n";
    }

    pi = 4;
    cout << "\npi calculated each 1000th iteration from 1 to 20000\n";
    for( i = 1; i < 21000; i++ )
    {
        pi = pi + doLeibniz( i );
        if( ( ( i - 1 ) % 1000 )  == 0 )
            cout << fixed << setprecision( 5 ) << pi << "\t" << i - 1 << "\n";
    }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top