Zack
Zack

Reputation: 23

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;
}

Upvotes: 1

Views: 991

Answers (2)

Bob__
Bob__

Reputation: 12749

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

Upvotes: 1

Adi Levin
Adi Levin

Reputation: 5233

Your program will never terminate, because test==p will never be true. This is a comparison between two double-precision numbers that are calculated differently. Due to round-off errors, they will not be identical, even if you run an infinite number of iterations, and your math is correct (and right now it isn't, because the value of PI in your program is not accurate).

To help you figure out what's going on, print the value of test in each iteration, as well as the distance between test and pi, as follows:

#include<iostream>
using namespace std;

void main() {
    double pi = atan(1.0) * 4; // Make sure you have a precise value of PI
    double sign = 1.0, sum = 0.0;
    for (int i = 1; i < 1000; i += 2) {
        sum = sum + (1.0 / i) * sign;
        sign = -sign;
        double test = 4 * sum;
        cout << test << " " << fabs(test - pi) << "\n";
    }
}

After you make sure the program works well, change the stopping condition eventually to be based on the distance between test and pi.

for (int i=1; fabs(test-pi)>epsilon; i+=2)

Upvotes: 0

Related Questions