Today is March 14th, which coincidentally represents the first three digits of the mathematical constant $\pi$. Therefore, the mathematics community has designated this day as $\pi$ Day.

$\pi$ is perhaps the most famous irrational number, and exploration of $\pi$ has never ceased. To date, with the help of computers, we have calculated $\pi$ to $31.4$ trillion decimal places! This record was set by a Japanese programmer from Google named Haruka Iwao. It is said that the calculation program ran on $25$ virtual machines for $121$ days, involving $170$ TB of data, ultimately achieving an accuracy of $31.4$ trillion decimal places for $\pi$.

Calculating the precision of $\pi$ has also been a method to measure computational power, a practice that began with John von Neumann. To this day, many mathematicians are tirelessly studying various properties of $\pi$, with some even believing that the digits of $\pi$ contain the ultimate secrets of the universe. Today, I will use Python to visualize $\pi$ and see what astonishing patterns might emerge.

Ideas

First of all, I downloaded the first 1 million decimal places of $\pi$ from the internet and saved them in a text file. The data is arranged with 50 digits per line, and it looks like this:

14159265358979323846264338327950288419716939937510
58209749445923078164062862089986280348253421170679
82148086513282306647093844609550582231725359408128
48111745028410270193852110555964462294895493038196
44288109756659334461284756482337867831652712019091
45648566923460348610454326648213393607260249141273
72458700660631558817488152092096282925409171536436

Then I will visualize these $10$ digits $[0-9]$ using certain rules. Currently, I have $2$ ideas:

  1. Dot Diagram: Assign a color to each of the $10$ digits $[0-9]$, and then draw dots sequentially.
  1. Line Diagram: Assign a color and an angle to each of the $10$ digits $[0-9]$, and draw connected line segments.

Dot Diagram

It is not complicated to draw dot diagram. First, define dot colors:

# Dot outline colors
color = ['gold', 'goldenrod', 'red', 'firebrick', 'mediumvioletred', 'darkorchid', 'royalblue', 'lightseagreen', 'mediumseagreen', 'olivedrab']
# Dot fill colors
color_fill = ['khaki', 'moccasin', 'lightcoral', 'lightsalmon', 'orchid', 'mediumpurple', 'skyblue', 'aquamarine', 'lightgreen', 'palegreen']

Then use the numbers $[0-9]$ as the color index to get dot color. The code to draw a single dot is as follows:

def draw_dot(n: int, c: int):
    """ Draw dots
    
    :param n: number in the place
    :param c: place in the decimal part
    :return: None
    """
    t.color(color_fill[n])
    t.begin_fill()
    t.circle(10)
    t.end_fill()
    t.color(color[n])
    t.circle(10)
    pos = t.pos()

After drawing a dot, the turtle moves to the next position, and here I set it to break line each 40 dots:

def move(c: int):
    """ Mode to next position

    :param c: place in the decimal part 
    :return: None
    """
    pos = t.pos()
    t.penup()
    if c % 40 == 0: #break line each 40 dots
        t.goto(-600, pos[1] - 30)
    else:
        t.goto(pos[0] + 30, pos[1])
    t.pendown()

Finally, we just read the decimal part of $\pi$ and draw the dots in a loop.

import turtle

turtle.setup(1.0, 1.0)
t = turtle.Turtle()
t.hideturtle()
t.pensize(2)
t.penup()
t.goto(-600, 400)
t.pendown()
t.speed(0)

# Draw dot 3 to represent the integer part
count = 1
num = 3
draw_dot(num, count)
move(count)

# Loop drawing decimal parts
with open('top-1-million-digits-of-pi.txt') as f:
    for i in range(28): # draw 28*50=1400 dots
        word = f.readline().strip()
        for a in word:
            num = int(a)
            count += 1
            draw_dot(num, count)
            move(count)
    f.close()
    
turtle.done()

Let's take a look at the final result.

Line Diagram

With a basic understanding of dot diagram, drawing line diagram is relatively simple. Here's the code directly:

import turtle

turtle.setup(1.0, 1.0)
t = turtle.Turtle()
t.hideturtle()
t.pensize(2)
t.pendown()
t.left(90)
t.speed(0)
color = ['gold', 'goldenrod', 'red', 'firebrick', 'mediumvioletred', 'darkorchid', 'royalblue', 'lightseagreen', 'mediumseagreen', 'greenyellow']

# Draw dot 3 to represent the integer part
last_num = 3
t.color(color[last_num])
t.right(last_num * 36)
t.forward(40)

# Loop drawing decimal parts
with open('top-1-million-digits-of-pi.txt') as f:
    for i in range(100):
        word = f.readline().strip()
        for a in word:
            current_num = int(a)
            t.color(color[current_num])
            angle = (current_num - last_num) * 36
            t.right(angle)
            t.forward(20)
            last_num = current_num
    f.close()

turtle.done()

Let's take a look at the final result.

Conclusion

How is it? Amazing, right? If you have any better ideas for visualization, feel free to leave a comment and share.

Finally, Happy $\pi$ Day to everyone!