Calculating Pi with Python


3 min read

Today's date is March 14 (3.14), and if you're a math nerd you know what that means - it's Pi Day!

There's an irrational (pun intended) sort of reverence held around pi - even though it's just a number, everyone seems to be amazed by its transcendental nature. Some people celebrate by eating pies, others by memorizing thousands of digits. Today, I'm going to try to compute as many digits as possible with Python.


Pi can't be represented as a ratio of integers, nor does it have an end. The approximate decimal representation in Python is as below:

import math

> 3.141592653589793

Unfortunately, it doesn't go past 16 digits. You can't just plug in some other formula to Python and have it spit out the result to a given number of digits. The real solution involves something much more complicated.

Using Regular Polygons

Circles are closely related to pi, as it's defined as the ratio between a circle's circumference and diameter, or C/D. This doesn't mean that it's rational, however, because either the circumference or diameter is irrational. The only way to approximate pi by using this C/D formula is to use a circumference that is rational.

Obviously, triangles don't have the same shape as circles. Neither do squares. But as you move from pentagons to hexagons to heptagons to octagons and beyond, the shape becomes more and more circle-like. You could even define a circle as a regular polygon with an infinite amount of sides.

Around 250 BC, the famed Greek mathematician Archimedes devised a way to estimate pi to more and more digits by finding the perimeter of regular polygons with successively more sides, then dividing by the diameter.

The formula for finding the radius of a regular polygon is:

$$ r = \frac{s}{2sin(\frac{180}{n})} $$

where r is the radius, s is the side length, and n is the number of sides. Let's build a simple Python program that calculates this and divides the circumference by the radius to get pi:

import math

def pi_with_polygons(side_length, num_sides):

    perimeter = side_length * num_sides
    print(f"Perimeter: {perimeter}")

    radius = side_length / (2 * math.sin(math.radians(180/num_sides))) #convert to radians first
    print(f"Radius: {radius}")

    pi = perimeter / (2 * radius)
    print(f"Pi: {pi}")

Calling pi_with_polygons(1, 5) for a pentagon gives:

Perimeter: 5
Radius: 0.8506508083520399
Pi: 2.938926261462366

Not even close. Maybe a 50-sided polygon will work?

Perimeter: 50
Radius: 7.962985554954328
Pi: 3.1395259764656687

Getting better. Archimedes used a 96-sided polygon:

Perimeter: 96
Radius: 15.281601954539683
Pi: 3.1410319508905093

There's the familiar 3.14. As the number of sides gets bigger, so does the accuracy:

pi_with_polygons(1, 100000000)

Perimeter: 1000000000
Radius: 159154943.09189534
Pi: 3.141592653589793

This works really well - the last result was accurate to 16 digits. The only limitation now is Python's support for long decimals. Hopefully I'll find a workaround for that soon, but for now I hope you're having a great Pi Day!

Did you find this article valuable?

Support Gabe Tao by becoming a sponsor. Any amount is appreciated!