Question

How can I write a function which will return pi (π) to a given number of decimal places?

Speed is not a concern. I've been looking at http://bellard.org/pi/, but I still don't understand how to get the nth digit of pi.

Was it helpful?

Solution

In calculus there is a thing called Taylor Series which provides an easy way to calculate many irrational values to arbitrary precision.

Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ...
(from http://www.math.hmc.edu/funfacts/ffiles/30001.1-3.shtml )

Keep adding those terms until the number of digits of precision you want stabilize.

Taylor's theorem is a powerful tool, but the derivation of this series using the theorem is beyond the scope of the question. It's standard first-year university calculus and is easily googlable if you're interested in more detail.


I didn't mean to imply that this is the most practical method to calculate pi. That would depend on why you really need to do it. For practical purposes, you should just copy as many digits as you need from one of the many published versions. I was suggesting this as a simple introduction of how irrational values can be equated to infinite series.

OTHER TIPS

There are many algorithms for numeric approximation of π.

As an alternative to JeffH's method of storing every variation, you can just store the maximum number of digits and cut off what you don't need:

#include <string>
#include <iostream>
using std::cout; using std::endl; using std::string;

// The first 99 decimal digits taken from:
// http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html
// Add more as needed.
const string pi =
  "1415926535"
  "8979323846"
  "2643383279"
  "5028841971"
  "6939937510"
  "5820974944"
  "5923078164"
  "0628620899"
  "8628034825"
  "342117067";

// A function in C++ that returns pi to X places
string CalcPi(const size_t decimalDigitsCount) 
{
  string returnValue = "3";
  if (decimalDigitsCount > 0)
  {
    returnValue += "." + pi.substr(0, decimalDigitsCount);
  }
  return returnValue;
} 

int main()
{
  // Loop through all the values of "pi at x digits" that we have. 
  for (size_t i = 0; i <= pi.size(); ++i) 
  {
    cout << "pi(" << i << "): " << CalcPi(i) << endl;
  } 
}

http://codepad.org/6mqDa1zj

I believe the algorithm you're looking for is what's known as a "Spigot Algorithm." One particular kind is the BBP (Bailey-Borwein-Plouffe) formula.

I believe that's what you're looking for.

Try "Computation of the n'th digit of pi in any base in O(n^2)". It's probably the fastest known algorithm that doesn't require arbitrary (read huge) precision floats, and can give you the result directly in base 10 (or any other).

"π IN THE MANDELBROT SET" explores the curious relationship between a sequence of points on the complex plane and how computing their "Mandelbrot number" (for lack a better term ... the number of iterations required to determine that the points in the sequence are not members of the Mandelbrot set) relates to PI.

Practical? Probably not.

Unexpected and interesting? I think so.

Are you willing to look up values instead of computing them?

Since you didn't explicitly specify that your function has to calculate values, here's a possible solution if you are willing to have an upper limit on the number of digits it can "calculate":

// Initialize pis as far out as you want. 
// There are lots of places you can look up pi out to a specific # of digits.
double pis[] = {3.0, 3.1, 3.14, 3.141, 3.1416}; 

/* 
 * A function that returns pi out to a number of digits (up to a point)
 */
double CalcPi(int x)
{
    // NOTE: Should add range checking here. For now, do not access past end of pis[]
    return pis[x]; 
}

int main()
{
    // Loop through all the values of "pi at x digits" that we have.
    for (int ii=0; ii<(int)sizeof(pis)/sizeof(double); ii++)
    {
        double piAtXdigits = CalcPi(ii);
    }
}

Writing CalcPi() this way (if it meets your needs) has a side benefit of being equally screaming fast for any value of X within your upper limit.

I'd start with the formula

pi = 16 arctan (1/5) - 4 arctan (1/239)

Google will easily find a proof for this formula that normal human beings can understand, and a formula to calculate the arc tangent function. This will allow you to calculate a few thousand decimal digits of pi quite easily and quickly.

You can tell the precision based on the last term you added (or subtracted). Since the amplitude of each term in Alan's sequence is always decreasing and each term alternates in sign, the sum won't change more than the last term.

Translating that babble: After adding 1/5, the sum won't change more than 1/5, so you are precise to within 1/5. Of course, you'll have to multiply this by 4, so you're really only precise to 4/5.

Unfortunately, math doesn't always translate easily into decimal digits.

My two cents... This might not be the fastest, but I think it's quite easy to understand. I came up with it myself during a math lecture, and I haven't really seen it anywhere else in literature. Either I'm a genius, really stupid, or don't really pay attention to reading books about math, or all of the above... :)

Anyway... Start with the unit circle. We know that x^2+y^2=1, so y=sqrt(1-x^2). We also know that the area of the unit circle is PI. If we now take the integral of the function sqrt(1-x^2) in the range 0 to 1, we will get a quarter of PI. So multiply it by 4 to get PI:

PI formula

If we would try to solve this analytically, I'm sure we would just get PI back. But it's quite easy to write a program to solve it numerically. The following one is in C:

#include <math.h>
#include <stdio.h>

void main(void) {
    double interval=0.0000001,area=0,x,y;

    for (x=0; x<1; x+=interval)
        area+=4*interval*sqrt(1-x*x);

    printf("pi ~ %.20f\n",area);
}

Running it with the above setting for interval, we get:

pi ~ 3.14159285415672595576

So 10,000,000 iterations give 6 correct decimals. Not the most efficient, but it's my baby... :)

pi = function () {
    let pi = 3;
    let a = 3;
    let even = false;
    let turn;

    while (a <= 90000) {
        turn = (4/((Math.pow(a, 3)) - (a)));

        if(even){
            turn = turn*-1;
            even = false;
        } else {
            even = true;
        }
        pi = pi + turn;
        a = a + 2;
    }
    return pi;
};

Consider this a rough sketch, but it is a straightforward approach that a beginner could implement.

int x = 9;
double pi = double(22/7);
String piAsString = pi.toString();
String valueAtXPosition = piAsString.subString(x, x+1);
int valueAtXPosAsInt = Integer.parseInt(valueAtXPosition);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top