tags:

views:

4659

answers:

16

How can I calculate the value of PI using C#?

I was thinking it would be through a recursive function, if so, what would it look like and are there any math equations to back it up?

I'm not too fussy about performance, mainly how to go about it from a learning point of view.

+3  A: 

This question has a bunch of good solutions from an algorithmic perspective. I wouldn't think it'd be hard to adapt one of them to c#.

Mark Biek
A: 

Calculate like this:

x = 1 - 1/3 + 1/5 - 1/7 + 1/9  (... etc as far as possible.)
PI = x * 4

You have got Pi !!!

This is the simplest method I know of.

The value of PI slowly converges to the actual value of Pi (3.141592165......). If you iterate more times, the better.

Niyaz
+15  A: 

If you want recursion:

PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...))))

This would become, after some rewriting:

PI = 2 * F(1);

with F(i):

double F (int i) {
    1 + i / (2.0 * i + 1) * F(i + 1);
}

Isaac Newton (you may have heard of him before ;) ) came up with this trick. Note that I left out the end condition, to keep it simple. In real life, you kind of need one.

wvdschel
A: 

Here is an article on Calculating PI in C#:

http://www.boyet.com/Articles/PiCalculator.html

Espo
+6  A: 

How about using:

double pi = Math.PI;

If you want better precision than that, you will need to use an algorithmic system and the Decimal type.

Skizz

Skizz
I think it a rare case when you would need to have more precision than you get from Math.PI;
Chris Ballance
+2  A: 

In any production scenario, I would compel you to look up the value, to the desired number of decimal points, and store it as a 'const' somewhere your classes can get to it.

(unless you're writing scientific 'Pi' specific software...)

Anthony Mastrean
+2  A: 

Good overview of different algorithms:

I'm not sure about the complexity claimed for the Gauss-Legendre-Salamin algorithm in the first link (I'd say O(N log^2(N) log(log(N)))).

I do encourage you to try it, though, the convergence is really fast.

Also, I'm not really sure about why trying to convert a quite simple procedural algorithm into a recursive one?

Note that if you are interested in performance, then working at a bounded precision (typically, requiring a 'double', 'float',... output) does not really make sense, as the obvious answer in such a case is just to hardcode the value.

OysterD
A: 

public double PI = 22.0/7.0;

DrPizza
PI == 3.14159...22.0 / 7.0 == 3.14285...Hardly a precise answer.
Joshua Carmody
+1  A: 
double PI = Math.PI;
Dmitry Shechtman
A: 

Regarding...

... how to go about it from a learning point of view.

Are you trying to learning to program scientific methods? or to produce production software? I hope the community sees this as a valid question and not a nitpick.

In either case, I think writing your own Pi is a solved problem. Dmitry showed the 'Math.PI' constant already. Attack another problem in the same space! Go for generic Newton approximations or something slick.

Anthony Mastrean
A: 

Here's a nice approach (from the main Wikipedia entry on pi); it converges much faster than the simple formula discussed above, and is quite amenable to a recursive solution if your intent is to pursue recursion as a learning exercise. (Assuming that you're after the learning experience, I'm not giving any actual code.)

The underlying formula is the same as above, but this approach averages the partial sums to accelerate the convergence.

Define a two parameter function, pie(h, w), such that:

pie(0,1) = 4/1
pie(0,2) = 4/1 - 4/3
pie(0,3) = 4/1 - 4/3 + 4/5
pie(0,4) = 4/1 - 4/3 + 4/5 - 4/7
... and so on

So your first opportunity to explore recursion is to code that "horizontal" computation as the "width" parameter increases (for "height" of zero).

Then add the second dimension with this formula:

pie(h, w) = (pie(h-1,w) + pie(h-1,w+1)) / 2

which is used, of course, only for values of h greater than zero.

The nice thing about this algorithm is that you can easily mock it up with a spreadsheet to check your code as you explore the results produced by progressively larger parameters. By the time you compute pie(10,10), you'll have an approximate value for pi that's good enough for most engineering purposes.

joel.neely
+1  A: 

What is PI? The circumference of a circle divided by its diameter.

In computer graphics you can plot/draw a circle with its centre at 0,0 from a initial point x,y, the next point x',y' can be found using a simple formula: x' = x + y / h : y' = y - x' / h

h is usually a power of 2 so that the divide can be done easily with a shift (or subtracting from the exponent on a double). h also wants to be the radius r of your circle. An easy start point would be x = r, y = 0, and then to count c the number of steps until x <= 0 to plot a quater of a circle. PI is 4 * c / r or PI is 4 * c / h

Recursion to any great depth, is usually impractical for a commercial program, but tail recursion allows an algorithm to be expressed recursively, while implemented as a loop. Recursive search algorithms can sometimes be implemented using a queue rather than the process's stack, the search has to backtrack from a deadend and take another path - these backtrack points can be put in a queue, and multiple processes can un-queue the points and try other paths.

A: 

There are a couple of really, really old tricks I'm surprised to not see here.

atan(1) == PI/4, so an old chestnut when a trustworthy arc-tangent function is present is 4*atan(1).

A very cute, fixed-ratio estimate that makes the old Western 22/7 look like dirt is 355/113, which is good to several decimal places (at least three or four, I think). In some cases, this is even good enough for integer arithmetic: multiply by 355 then divide by 113.

355/113 is also easy to commit to memory (for some people anyway): count one, one, three, three, five, five and remember that you're naming the digits in the denominator and numerator (if you forget which triplet goes on top, a microsecond's thought is usually going to straighten it out).

Note that 22/7 gives you: 3.14285714, which is wrong at the thousandths.

355/113 gives you 3.14159292 which isn't wrong until the ten-millionths.

Acc. to /usr/include/math.h on my box, M_PI is #define'd as: 3.14159265358979323846 which is probably good out as far as it goes.

The lesson you get from estimating PI is that there are lots of ways of doing it, none will ever be perfect, and you have to sort them out by intended use.

355/113 is an old Chinese estimate, and I believe it pre-dates 22/7 by many years. It was taught me by a physics professor when I was an undergrad.

A: 

@Thomas Kammeyer:

Note that Atan(1.0) is quite often hardcoded, so 4*Atan(1.0) is not really an 'algorithm' if you're calling a library Atan function (an quite a few already suggested indeed proceed by replacing Atan(x) by a series (or infinite product) for it, then evaluating it at x=1.

Also, there are very few cases where you'd need pi at more precision than a few tens of bits (which can be easily hardcoded!). I've worked on applications in mathematics where, to compute some (quite complicated) mathematical objects (which were polynomial with integer coefficients), I had to do arithmetic on real and complex numbers (including computing pi) with a precision of up to a few million bits... but this is not very frequent 'in real life' :)

You can look up the following example code.

OysterD
A: 

@OysterD: He didn't so much ask for an algorithm as a method of computation. He wasn't clear about whether he wanted to learn how the computation is done or just a reasonable way to get at the value... so I decided most anything was fair game. And while I'll admit a series expansion is the usual way many trig functions are evaluated in library functions, it's also true that, as a matter of practicality it's rare to actually write those loops. Unless you have a need for something more specialized. As I pointed out: there are many, many ways to get at this question and they have to be divided up by the needs of the moment.

A related, less practical, but fun question: what is the Kolmogorov complexity of a string consisting of the first N digits of PI?

Thomas Kammeyer