Eight ways to find the approximate value of π

Table of contents

introduction

1. Math library

2. Monte Carlo

3. Riemann sum (definite integral)

4. John Wallis

5. Gregory-Leibniz

6. Nilakantha

7. Vedic formula (Francois Viete)

8. Continued fractions

9. Comparison of various methods

10. Summary

introduction

Speaking of pi, two people have to be mentioned-Liu Hui and Zu Chongzhi. Liu Hui's circle cutting technique is based on the inscribed regular polygon of the circle, and he uses the area of ​​the regular polygon to approximate the area of ​​the circle. The more divisions, the smaller the area between the inscribed regular polygon and the circle, and the closer the two become. After infinite division, the inscribed regular polygon and the circle will merge into one. On the basis of Liu Hui, Zu Chongzhi set up a circle with a diameter of one foot, and cut and calculated within the circle. When he cut to the inscribed one hundred and ninety-two polygons of the circle, he got the value of "heroic rate". He continued cutting, making three hundred and eighty-four polygons, seven hundred and sixty-eight polygons... until he cut to twenty-four thousand five hundred and seventy-six polygons. Zu Chongzhi calculated the side lengths of each inscribed regular polygon in turn. Finally, a circle with a diameter of one foot is obtained, and its circumference is between three feet, one foot, four inches, one minute, five centimeters, two centimeters, seven seconds, and three feet, one foot, four inches, one minute, five centimeters, nine milliseconds, and six seconds. . In the end, he calculated the value of pi to be between 3.1415926 and 3.1415927, which is a great achievement! It was not until 1,000 years later that the 15th-century Arabic mathematician Al Qassi and the 16th-century French mathematician Viet surpassed him.

And now, with computers, we no longer need to use circumcision to find the value of pi. Next, I will introduce several methods of finding pi, hoping to help you in your study.

1. Math library

import math
pi = math.pi
print(pi)
# 运行结果为:3.141592653589793

The math library is a function library with built-in mathematics. It does not support complex numbers (if readers need it, you can use the built-in function complex that comes with python). It only supports integer and floating-point operations. The math library provides a total of:

  • 4 numeric constants
  • 44 functions, divided into 4 categories:
    16 numerical representation functions,
    8 power logarithmic functions,
    16 trigonometric logarithmic functions,
    4 advanced special functions

And the pi we need is one of the 4 digital constants, which can be called directly by math.pi.

Output result: 3.141592653589793.

2. Monte Carlo

The Monte Carlo method, also known as the computer stochastic simulation method, is a calculation method based on "random numbers". Simply put, it is continuous sampling and gradually approaching the result.

import numpy as np
import matplotlib.pyplot as plt

# Draw a square and a circle
squareX = [1,-1,-1,1,1] # x coordinates of square
squareY = [1,1,-1,-1,1] # y coordinates of square

circleX,circleY = [],[]

for i in range(361):
    circleX.append(np.cos(np.pi*i/180)) # x coordinates of circle
    circleY.append(np.sin(np.pi*i/180)) # y coordinates of circle

plt.rcParams['figure.figsize'] = [16, 8] # figure size
fig, ax = plt.subplots(1)
ax.plot(squareX, squareY, color='black')
ax.plot(circleX, circleY, color='b')
ax.set_aspect('equal')
plt.show()

We run the above code, we can get the following picture:

This is a square with a radius of 1 and an area of ​​2*2=4. Inscribed a unit circle, the area is 1*1*π=π. In this way, the ratio of the area of ​​the circle to the area of ​​the square is π/4. Randomly add multiple points to this graph, and count the number of points falling inside the circle. Then use the counted points/total points to approximate the value of π/4, so that the value of π can be approximated. The more total points taken, the better the simulation effect and the more accurate the π value. The code is as follows:

import numpy as np
import matplotlib.pyplot as plt
def monte_carlo_pi(N):
    number_inside = 0
    points_inside = [[], []]
    points_outside = [[], []]
    current_pi = []
    i = 0
    count = 0
    # n 为传入的总点数量
    while i < N:
        # 随机产生x,y坐标
        x, y = np.random.uniform(-1, 1, 2)
        # 如果x平方 + y平方 < 1,说明在圆内
        if (pow(x, 2) + pow(y, 2)) < 1:
            number_inside += 1
            points_inside[0].append(x)
            points_inside[1].append(y)
        else:
            points_outside[0].append(x)
            points_outside[1].append(y)
        current_pi.append(4 * number_inside /(i+1))
        i += 1
    # π的值为:4 * (落在圆内的点/总的点)
    return (points_inside, points_outside, current_pi)

Call the function, and do a simple visualization:

import numpy as np
import matplotlib.pyplot as plt
def monte_carlo_pi(N):
    number_inside = 0
    points_inside = [[], []]
    points_outside = [[], []]
    current_pi = []
    i = 0
    count = 0
    # n 为传入的总点数量
    while i < N:
        # 随机产生x,y坐标
        x, y = np.random.uniform(-1, 1, 2)
        # 如果x平方 + y平方 < 1,说明在圆内
        if (pow(x, 2) + pow(y, 2)) < 1:
            number_inside += 1
            points_inside[0].append(x)
            points_inside[1].append(y)
        else:
            points_outside[0].append(x)
            points_outside[1].append(y)
        current_pi.append(4 * number_inside /(i+1))
        i += 1
    # π的值为:4 * (落在圆内的点/总的点)
    return (points_inside, points_outside, current_pi)
# To see the entire image, go to Cell --> All Outputs --> Toggle Scrolling

N = 5000
# Generate a bunch of x and y values between -1 and 1
points_inside, points_outside, current_pi = monte_carlo_pi(N)

# Draw a square and a circle to frame out the simulation
squareX = [1,-1,-1,1,1]
squareY = [1,1,-1,-1,1]

circleX,circleY = [],[]

for i in range(361):
    circleX.append(np.cos(np.pi*i/180))
    circleY.append(np.sin(np.pi*i/180))


plt.rcParams['figure.figsize'] = [16, 8]

fig, (ax1, ax2) = plt.subplots(1,2)
ax1.plot(squareX, squareY, color='black')
ax1.plot(circleX, circleY, color='b')
ax1.scatter(*points_inside, c='g', marker='.')
ax1.scatter(*points_outside, c='r', marker='.')
ax1.set_aspect('equal')

ax2.plot(range(N), current_pi)
ax2.axhline(y=np.pi, c='r', ls='--')
ax2.axis([0, N, 0, 4])
plt.show()

print("Final pi: ", current_pi[-1])

The picture on the left is the simulation effect picture, the points inside the circle are marked in green, and the points outside the circle are marked in red. The figure on the right is the calculated value of π. It can be seen that when the total number of points increases, the value of π becomes more and more stable, and it keeps approaching the true value of π. When the total number of points is 5000, the calculated π value is: 3.1624. If you are interested, you can also keep increasing the total number of points (N) to see when you can exceed the accuracy calculated by Zu Chongzhi!

3. Riemann sum (definite integral)

This is the knowledge of high numbers. Compute an approximation of pi using the Riemann sum to approximate the area of ​​the first quadrant of the unit circle. The abscissa of the unit circle is divided into N points, the width of each rectangle is 1/N, and the height is the function value of sqrt(1-x**2).

code show as below:

import math
def Riemann_pi(N):
    pi = 0
    fin_sum = 0
    for i in range(0,N):
        mid = (i+0.5)/N
        fin_sum += 1/N * math.sqrt(1-mid**2)
    pi = fin_sum*4
    return pi

 This is the form of definite integral, which divides an irregularly shaped object into countless rectangles, and the sum of the areas of these rectangles is the area of ​​the original irregular object.

The output result: 3.1415929980246284, the accuracy is still relatively high.

4. John Wallis

Give the formula directly:

 code:

def Wallis_pi(N):
    sum_1 = 2
    pi = 0
    if N%2 != 0:
        for i in range(3,N+1,2):
            sum_1 *= ((i-1)/i)*((i+1)/i)
        pi = sum_1*2
    else:
        for i in range(3,N+1,2):
            sum_1 *= ((i-1)/i)*((i+1)/i)
        sum_1 *= (N/(N+1))
        pi = sum_1*2
    return (pi)

Directly set sum_1 = 2, which can reduce the number of iterations, so that you can start directly from 3, and add 2 to the denominator with range; and note that the input N=4 and N=3 are different; N is a total of several fractions Multiplication, for example, N=4, then the first four items in the formula are multiplied together; if there is no need to judge and separate, N = 3 and N=4 will become the same result. So I used if N%2==0 to judge here. Then you can multiply by the formula. I always feel that what is written here is a bit complicated. If readers have any good ideas, they are welcome to communicate!

Run the code, pass in N = 100 to get π = 3.126078900215409, N = 10000, get π = 3.141435593589866

5. Gregory-Leibniz

The formula is as follows:

 

 code:

def sign(n):
    if n%4 == 1 :
        return 1
    else:
        return -1

def arctan_pi(N):
    pi = 0
    fin_sum = 0
    for i in range(1,N+1):
        fin_sum += (4/(sign(2*i-1)*(2*i-1)))
    pi = fin_sum
    return (pi)

 First of all, you can see that there is a positive and negative sign in the formula, so I first defined a function sign to judge the positive and negative sign. According to the characteristics of the denominator of the formula, when %4==1, it is a positive sign, so return 1;%4 When ==3, it is a negative sign, so return -1; then write it according to the formula, and understand the above code block after understanding 2*i-1. You can go through the program with a few numbers first, I believe you will understand it soon.

After 100 iterations, π= 3.1315929035585537 After 10001 iterations, π= 3.1416926435905346

6. Nilakantha

official:

code:

import numpy as np
def Nilakantha_pi(N):
    pi = 0
    fin_sum = 0
    if N > 1:
        return (-1)**(N-1)*4/(2*N*(2*N+1)*(2*N+2)) + Nilakantha_pi(N-1)
    else:
        return 1/6+3

 Here I use the idea of ​​recursion, because it is a summation formula; recursion can not only effectively reduce the amount of code, but also make the program more orderly; although the problem that recursion can solve can be solved by loop, but learn well Recursion is necessary! Students who are not familiar with recursion can first learn the recursive calculation method of the Fibonacci sequence.

Python Fibonacci recursive method

In the code, if judges, keep N-1, and when N=1, execute else. It is worth noting that the last item of return needs to be added 3 on this basis, so that an approximate value of π can be obtained.

After 100 iterations, π= 3.1415924109719824

7. Vedic formula (Francois Viete)

official:

 code:

from math import sqrt
import numpy as np
def Viete_pi(N):
    a = sqrt(2)
    all_a = sqrt(2)
    for i in range(1,N):
        a = sqrt(2+a)
        all_a *= a
    num_1 = all_a
    num_2 = 2**N
    pi = 2/(num_1/num_2)
    return pi

This is a multiplication problem of continuous nesting. I separate a from all_a, let a continue to nest, and let all_a and a perform cumulative multiplication; and note that my denominator and numerator are calculated separately, and all_a returned as num_1 is The numerator and denominator are 2**N. After getting these two numbers, substitute them into the formula and do a simple transformation to calculate the value of pi.

After 100 iterations, π = 3.141592653589794.

Episode:

In the process of solving this problem, I accidentally saw the code written by another blogger. The link is as follows: Veda formula for π

# coding:utf-8
from math import sqrt
def Vieta():
#请在此添加代码
#********** Begin *********#
    a = sqrt(2)/2.0
    yield a
    while True:
        a = sqrt((1+a)/2.0)
        yield a
#**********  End  *********#
N = int(input())
v = Vieta(); p = 1.0
for i in range(N+1):
#请在此添加代码
#********** Begin *********#
    p *= next(v)
#**********  End  *********#
print ("%.6f"%(2.0/p))

This code makes me a little confused. The main thing is that I don't understand the keyword yield.

What is this yield? Ancient memories are beginning to wake up. I seem to have come into contact with them before. Let me add two experience posts first:

python yield keyword

Four minutes to explain python yield

According to my understanding:

  • It can be regarded as return in a superficial way, and the program will not proceed when it reaches there.
  • No matter where yield appears in the function, the function will become a generator.
  • The function does not start executing until the next method is called, and returns the value after yield to the previous parameter.
  • Using the yield keyword can effectively save time and space.

8. Continued fractions

official:

 code:

import numpy as np
def CF_pi_1(k, N):
    pi = 0
    if k < N:
        k += 1
        return 2*k-3 + (k-1)**2/CF_pi_1(k,N)
    else:
        return 2*k-1
def CF_pi(k, N):
    return 4/CF_pi_1(k,N)

It is also processed by recursion, but this time it is different from the above. His final result needs to be removed by 4, but no matter which return statement is placed in the if-else, it is easy to find that it does not meet expectations after a little calculation. Effect. So another function was created to accept the value of the previous function and process it. This separates the two parts. If the title requires only one function to complete, I have no idea now. If readers have any good ideas, they are also welcome to exchange private messages.

If you can't understand this code, you can take a look at the real question of the 2013 Blue Bridge Cup: 2013 Blue Bridge Cup Golden Consecutive Score

After 5 iterations, π = 3.142342342342342.

9. Comparison of various methods

Comparison of various methods for finding π
method Take point/interval/number of iterations Approximate value of π sought
math library Just call it directly 3.141592653589793
Monte Carlo Take 5000 points 3.1624
Riemann sum (definite integral) Divide 10000 intervals 3.1415929980246284
John Wallis Iterate 10000 times 3.141435593589866
Gregory-Leibniz Iterate 10001 times 3.1416926435905346
Nilakantha Iterate 100 times 3.1415924109719824
Vedic formula (Francois Viete) Iterate 100 times 3.141592653589794
Continued fractions Iterate 5 times 3.142342342342342

10. Summary

The above are several ways to find pi that I will introduce today. If you need to use π in daily life, most of them can be solved with math.pi, which is very convenient. The Monte Carlo method is often used in mathematical modeling. If you are interested, you can also look at the probability problem of Buffon's needle. The Riemann sum is also a definite integral, which continuously divides the area and approximates the replacement of the sum. From John Wallis to continued fractions, it can be boiled down to the problem of finding π by series. The difference lies in the speed of convergence. Some need to iterate hundreds of thousands of times to have a better prediction value, while others It only takes 5 out of 10.

Later, if I encounter a problem related to π, I will not be able to write a formula to find it, and I will call math.pi directly, but this does not mean that this exploration process is meaningless. In this process, I have deepened my further understanding of recursion, gained a preliminary understanding of the yield keyword, strengthened my code logic ability, and most importantly, I have a sense of pride in constantly solving problems.

Due to the limited level, it is inevitable that there will be mistakes in the writing process. Readers are welcome to give me advice and corrections are welcome!

Guess you like

Origin blog.csdn.net/weixin_63866037/article/details/127220287