DEV Community

Nikita Pshenichny
Nikita Pshenichny

Posted on

Calculating Pi to million decimals in Python

Hello, world! A couple of days ago, I was surfing the net and saw this scary formula...

Chudnovsky

😳😳😳

P.S. Don't watch math videos on YouTube

...and decided to calculate the pi number. In the python math library, pi is stored only with the first 15 decimals. But as you could see from the title, I wanted to calculate many more characters. And I wanted to do it exactly in Python because it's my favorite programming languageπŸ’—. I've decided to use this ↗️ formula (it was deduced by Chudnovsky). But there're lots of factorials (it's hard to calculate them for computer) and very big numbers (it's hard to store them for computer). That's why I've started to look for the other formula for pi calculation. I've found these:

1

2

3

But I thought that I can find something better... and I was right. I found this brilliant formula. It was deduced exactly for computer calculations. Here it is:

AGM

That allows us to make an approximation for any large N:

equation (5)

It's the AGM (Arithmetic-Geometric Mean) formula. And at first glance, there is nothing understandable here, and at second glance too, but I have already written above that this formula was specifically derived for computer calculations. That is why it is not right to present it as a mathematical formula. I will show you my code a little bit later.

In the meantime, let's ask ourselves the following question: how can we check the accuracy of our calculations? After all, we can't know for sure if we've solved the problem correctly if we don't have the answers. So, here. I found the first billion decimal places of pi. I've trunked this file to million decimals and copied it to IDE. Now, we are ready to write some code.

😎😎...WRITING SOME CODE...πŸ’ͺ🀘

First, we need a library for working with numbers with a veeery large number of decimal places. So, python has a built-in library for such purposes.

from decimal import Decimal as d, getcontext as gc
Enter fullscreen mode Exit fullscreen mode

Decimal is a special data type for big numbers and we need getcontext().prec to set the precision of our calculations. Then, we get the right pi digits:

with open("pi", mode="r", encoding="utf-8") as file:
    digits = file.read().replace("\n", "")
Enter fullscreen mode Exit fullscreen mode

Now, let's start to write an interesting code.

def calc_pi(dp):
    gc().prec = dp + 3  # Set the precision
    a, n, g, series = d(1), d(1), 1 / d(2).sqrt(), d(.25)  # Set start values
    ...
Enter fullscreen mode Exit fullscreen mode

Then, let's change the values of the variables while the number is wrong:

while (a * a / series).quantize(d(f"1.{'0' * dp}")) != d(digits).quantize(d(f"1.{'0' * dp}")):
    ...
Enter fullscreen mode Exit fullscreen mode

Decimal.quantize(Decimal("1.0000...")) is a function for rounding Decimal numbers. a * a / series is our answer.

Now, let's make the main calculations:

...
series -= (a - g) * (a - g) * d(.25) * n  # Calculating denominator
n += n  # Instead of calculation 2 ** (k + 1) we just double this value
a, g = ((a + g) * d(.5), (a * g).sqrt())  # Update AGM values
Enter fullscreen mode Exit fullscreen mode

And then,

return (a * a / series).quantize(d(f"1.{'0' * dp}"))
Enter fullscreen mode Exit fullscreen mode

Here's the whole code:

πŸŒŸπŸ†!!!CONGRATULATIONS!!!πŸ†πŸŒŸ

Yeah, we did it! If you have misunderstood smth, just ask your question in the comments. Good luck. Bye!

P.S. And what about results?

This code calculates the first 5000 decimals in half of a second (yeah, not bad!). And the first 100000 in 15 seconds. But what about one million decimals? Yes, it's possible to calculate them in a couple of hours on my machine.

Top comments (0)