This project implements several numerical methods to estimate the value of
Two libraries used in this python script, math and random. Both of them are part of Python’s standard library. This means they're built-in and available for you to use right away without any additional installation.
- Open terminal
- Clone the repository:
git clone https://github.com/LittleBigPluton/Pi-Estimation.git
- Change directory:
cd Pi-Estimation
- To run the python script on terminal:
python3 main.py
Monte Carlo(1)
The Monte Carlo method uses random sampling to estimate quantities that are difficult to calculate directly. We use a geometric probability approach based on the areas of a circle and a square. We generate N random points uniformly distributed over the square. Since the points are uniformly distributed, the probability that a point falls within any subregion is proportional to the area of that subregion relative to the total area of the square. Consider a circle of radius 1 inscribed in a square of side length 2.
- The area of the circle is given by:
$$A_{\text{circle}} = \pi \times 1^2 = \pi$$ - The area of the square is:
$$A_{\text{square}} = 2 \times 2 = 4$$ - The probability P that a randomly chosen point falls inside the circle is:
$$P = \frac{A_{\text{circle}}}{A_{\text{square}}} = \frac{\pi}{4}$$
Let N be the number of points in the square. As N becomes larger, the ratio converges to the true probability:
By rearranging the relation, we obtain:
So by counting the fraction of points inside the circle and multiplying by 4, we can estimate the value of
The accuracy of the Monte Carlo estimation improves with the number of samples N. As N increases, the ratio
This approach shows how the fraction of points that fall within a specific region (the circle) is directly related to the area of that region relative to the total area of the space (the square).
For MC_PI_calculator function in pi_estimate.py file, two positive random numbers between [0.0,1.0] are selected to represent x and y coordinate pairs in Cartesian coordinate system. Imagine there is a square with side length 2 is lying on the first region of the coordinate system where left bottom corner of it is at the origin. Inside this square, there is a circle which origin is at (1,1) in the coordinate system.
# Generate data points
for i in range(0,attempts):
x = 1-random.uniform(0.0,2.0)
y = 1-random.uniform(0.0,2.0)
Then, it is checked the distance of this point from origin of the circle to see if it is inside the circle or not.
# Calculate point's distance from center of circle
point = math.sqrt(x*x+y*y)
# Check if the point is in the circle area or not
if point<=1:
inside_circle += 1
This procedure is repeated a million times,
# Calculate ratio of data point inside
return(inside_circle/attempts*4)
The following table shows how estimated
Number of attempt | Approximated \pi Value |
---|---|
10 | 2.0 |
2.92 | |
3.14 | |
3.124 | |
3.14112 | |
3.14142 |
Leibniz Formula(3)
The Leibniz formula (also known as the Gregory-Leibniz series) for
By setting x = 1, we obtain:
Multiplying both sides by 4 gives the Leibniz formula for
In practice, Leibniz_Formula function in pi_estimate.py file, the infinite series is truncated to a finite number of terms to approximate
estimation = 0
for k in range(attempts):
division = 1/(2*k+1)
if k%2 == 0:
estimation += division
else:
estimation -= division
return 4*estimation
Every for loop, the denominator is recalculated with respect to the current iteration. Then, to ensure the sign of the division, the k value is checked whether it is even or not and added or substitute from the cumulative value of estimation. Finally, the estimation is multiplied by 4 to return final result of the estimation after desired iteration reached. The approximation improves as the number of terms increases, though the convergence is relatively slow. For example, in our simulation results, the table shows how the approximation of
Number of Terms | Approximated \pi Value |
---|---|
3.04184 | |
3.13159 | |
3.14060 | |
3.14149 | |
3.14160 | |
3.14159 |
Nilakantha Series(4)
The Nilakantha series is an infinite series that provides an efficient approximation for
This can be written out explicitly as:
The series begins with the constant 3 and then adds and subtracts successive terms that involve the product of three consecutive even or odd numbers. The alternating signs and the decreasing magnitude of the terms ensure that the series converges to the value of
In practical applications, the infinite series is truncated to a finite number of terms to approximate
for i in range(attempts):
n = (i+1)*2
estimation += 4*(-1)**i/n/(n+1)/(n+2)
return estimation
During the finite iteration, the variable n is calculated according to the current attempt. Then, Estimation of
Number of Terms | Approximated |
---|---|
1 term | 3.16667 |
2 terms | 3.13333 |
3 terms | 3.14524 |
4 terms | 3.13968 |
5 terms | 3.14271 |
10 terms | 3.14141 |
100 terms | 3.14152 |
1000 terms | 3.14159 |
Gauss-Legendre(5)
The Gauss-Legendre algorithm is an iterative method that converges extremely quickly to
-
$a_0$ = 1,$b_0$ =$\frac{1}{\sqrt{2}}$ ,$t_0$ =$\frac{1}{4}$ ,$p_0$ = 1
Then, for each iteration n
$a_{n+1} = \frac{a_n + b_n}{2}$ $b_{n+1} = \sqrt{a_n , b_n}$ $t_{n+1} = t_n - p_n , (a_n - a_{n+1})^2$ $p_{n+1} = 2 , p_n$
After a sufficient number of iterations, the approximation for
This formula rapidly converges to
In practice, only a few iterations are needed to achieve high precision. After initialization of a,b,t and p values at the beginning, the inline functions for iterative values for
#Initialize values
a, b, t, p = 1, 1/math.sqrt(2), 1/4, 1
#Define next values of variables as inline function
a_next = lambda a,b: (a+b)/2
b_next = lambda a,b: math.sqrt(a*b)
t_next = lambda a,a_next,p,t: t-p*(a-a_next)**2
After this initializations, iterations occur by updating a,b,t and p values in each iteration.
#Calculate variables at the desired iteration
for _ in range(attempts):
a_n1 = a_next(a,b)
b = b_next(a,b)
t = t_next(a,a_n1,p,t)
p = p*2
a = a_n1
Finally, the estimated
#Return estimation
return ((a+b)**2)/4/t
For instance, after just 3 or 4 iterations, the approximation of
Iteration | Approximated |
---|---|
1 | 3.1405792 |
2 | 3.1415926 |
3 | 3.1415926 |
In real-world applications, the Gauss-Legendre algorithm can be used to compute
- Fork the repository.
- Create a new branch:
git checkout -b feature-name
. - Make your changes.
- Push your branch:
git push origin feature-name
. - Create a pull request.