0

I wrote a method that calculates PI (π) by using infinite series:

public static decimal NilakanthaGetPI(ulong n)//Nilakantha Series
{
    decimal sum = 0;
    decimal temp = 0;
    decimal a = 2, b = 3, c = 4;
    for (ulong i = 0; i < n; i++)
    {
        temp = 4 / (a * b * c);
        sum += i % 2 == 0 ? temp : -temp;
        a += 2; b += 2; c += 2;
    }
    return 3 + sum;
}

The method works fine till the number of iterations reaches a few billion which gives me a OverflowException which is logical because the value of temp is greater then the decimal type can hold. It came to my mind to use BigInteger but then I can't do the division temp = 4 / (a * b * c).With this method I can calculate the first 25 decimal digits of PI (decimal type can store 28 or 29 decimal digits). Is there a way to modify this method so that it can calculate more digits of PI?

Slaven Tojić
  • 2,945
  • 2
  • 14
  • 33
  • 1
    You could use [this](https://www.math.hmc.edu/funfacts/ffiles/20010.5.shtml) formula. It is probably going to be slow, but you won't need to store each digit. – FCin Mar 16 '18 at 13:29
  • @FCin I don't really need to calculate PI, I am just curious how to modify this method so it can calcualte more digits of PI. – Slaven Tojić Mar 16 '18 at 13:33
  • https://stackoverflow.com/questions/4523741/arbitrary-precision-decimals-in-c-sharp/4524254#4524254 – Ashley Medway Mar 16 '18 at 13:43

2 Answers2

0

You could use an arbitrary precision floating point library. Unfortunately, I didn't found a lot that is still maintained but this one might help you.

With APF Libraries you can calculate results with much bigger digit resolution at the cost of speed and memory. But for your example, it should be no problem.

Alex
  • 1,857
  • 3
  • 36
  • 51
0

Sure, here's a technique you can use.

BigInteger sumNumer = 3;
BigInteger sumDenom = 1;
BigInteger a = 2, b = 3, c = 4;
for (BigInteger i = 0; i < n; i++)
{
    BigInteger tempNumer = i % 2 == 0 ? 4 : -4;
    BigInteger tempDenom = (a * b * c);
    sumNumer = sumNumer * tempDenom + sumDenom * tempNumer;
    sumDenom = sumDenom * tempDenom;
    // TODO: reduce sum to a simpler fraction 
    a += 2; 
    b += 2; 
    c += 2;
}

When you're done the loop you'll have a numerator and denominator of a fraction that closely approximates pi. Now the problem is to turn that into decimal digits, which you can do easily enough simply by implementing the standard primary school long division algorithm.

Reducing the fraction to its simplest form and implementing long division is left as an exercise. Try it! It builds character.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067