Search code examples
c++loopspi

Counting iterations of the Leibniz summation for π in C++


My task is to ask the user to how many decimal places of accuracy they want the summation to iterate compared to the actual value of pi. So 2 decimal places would stop when the loop reaches 3.14. I have a complete program, but I am unsure if it actually works as intended. I have checked for 0 and 1 decimal places with a calculator and they seem to work, but I don't want to assume it works for all of them. Also my code may be a little clumsy since were are still learning the basics. We only just learned loops and nested loops. If there are any obvious mistakes or parts that could be cleaned up, I would appreciate any input. Edit: I only needed to have this work for up to five decimal places. That is why my value of pi was not precise. Sorry for the misunderstanding.

#include <iostream>
#include <cmath>
using namespace std;

int main() {

const double PI = 3.141592;
int n, sign = 1;
double sum = 0,test,m;

cout << "This program determines how many iterations of the infinite series   for\n"
        "pi is needed to get with 'n' decimal places of the true value of pi.\n"
        "How many decimal places of accuracy should there be?" << endl;
cin >> n;

double p = PI * pow(10.0, n);
p = static_cast<double>(static_cast<int>(p) / pow(10, n));
int counter = 0;
bool stop = false;

for (double i = 1;!stop;i = i+2) {
    sum = sum + (1.0/ i) * sign;
    sign = -sign;
    counter++;
    test = (4 * sum) * pow(10.0,n);
    test = static_cast<double>(static_cast<int>(test) / pow(10, n));

        if (test == p)
            stop = true;
}
cout << "The series was iterated " << counter<< " times and reached the value of pi\nwithin "<< n << " decimal places." << endl;
return 0;
}

Solution

  • One of the problems of the Leibniz summation is that it has an extremely low convergence rate, as it exhibits sublinear convergence. In your program you also compare a calculated extimation of π with a given value (a 6 digits approximation), while the point of the summation should be to find out the right figures.

    You can slightly modify your code to make it terminate the calculation if the wanted digit doesn't change between iterations (I also added a max number of iterations check). Remember that you are using doubles not unlimited precision numbers and sooner or later rounding errors will affect the calculation. As a matter of fact, the real limitation of this code is the number of iterations it takes (2,428,700,925 to obtain 3.141592653).

    #include <iostream>
    #include <cmath>
    #include <iomanip>
    
    using std::cout;
    
    // this will take a long long time...
    const unsigned long long int MAX_ITER = 100000000000;
    
    int main() {
    
        int n;
    
        cout << "This program determines how many iterations of the infinite series for\n"
                "pi is needed to get with 'n' decimal places of the true value of pi.\n"
                "How many decimal places of accuracy should there be?\n";
        std::cin >> n;
    
        // precalculate some values
        double factor = pow(10.0,n);
        double inv_factor = 1.0 / factor;
        double quad_factor = 4.0 * factor;
    
        long long int test = 0, old_test = 0, sign = 1;
        unsigned long long int count = 0;
        double sum = 0;
    
        for ( long long int i = 1; count < MAX_ITER; i += 2 ) {
            sum += 1.0 / (i * sign);
            sign = -sign;
            old_test = test;
            test = static_cast<long long int>(sum * quad_factor);
            ++count;
            // perform the test on integer values
            if ( test == old_test ) {
                cout << "Reached the value of Pi within "<< n << " decimal places.\n";
                break;          
            }
        } 
    
        double pi_leibniz = static_cast<double>(inv_factor * test);
        cout << "Pi = " << std::setprecision(n+1) << pi_leibniz << '\n';    
        cout << "The series was iterated " << count << " times\n";
    
        return 0;
    }
    

    I have summarized the results of several runs in this table:

    digits        Pi           iterations
    ---------------------------------------
     0        3                           8
     1        3.1                        26
     2        3.14                      628
     3        3.141                   2,455
     4        3.1415                136,121
     5        3.14159               376,848
     6        3.141592            2,886,751
     7        3.1415926          21,547,007
     8        3.14159265        278,609,764
     9        3.141592653     2,428,700,925
    10        3.1415926535   87,312,058,383