Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Monte Carlo Estimation of PI in Python
import random as r
import math as m
# Number of darts that land inside.
inside = 0
# Total number of darts to throw.
total = 1000
# Iterate for the number of darts.
for i in range(0, total):
# Generate random x, y in [0, 1].
x2 = r.random()**2
y2 = r.random()**2
# Increment if inside unit circle.
if m.sqrt(x2 + y2) < 1.0:
inside += 1
# inside / total = pi / 4
pi = (float(inside) / total) * 4
# It works!
print(pi)
@dandrewmyers
Copy link

dandrewmyers commented Apr 5, 2018

Made a version of your Monte Carlo pi code with a plot. Here is link:
https://github.com/dandrewmyers/numerical/blob/master/mc_pi.py

@laffra
Copy link

laffra commented Mar 13, 2019

I made a visualization for this code on PyAlgoViz.

@peduajo
Copy link

peduajo commented Oct 15, 2019

hmmm the code doesn't give me the pi number. I think that the equation is x² + y² <= 1, and you are doing sqrt(x² + y²) <= 1. I have checked this equation with a large number of points and it is really close to the pi number, like ~3.1415

@AndreaPasqualini
Copy link

AndreaPasqualini commented Feb 8, 2020

@peduajo: taking the square root in this specific case is not a problem. At worst, we mis-count points very much on the circle because of rounding error. This is because the circle (and the points inside it) is defined as the set of points (x, y) such that x^2 + y^2 <= r^2. If r=1, then the square root becomes irrelevant and we could as well check x^2 + y^2 <= 1. The problem is that the circle in the code is not the unit circle. By taking x and y from uniforms over [0, 1], we are using a circle inscribed in the unit square, which is not the unit circle but is the half-unit circle.

@vwang0
Copy link

vwang0 commented Apr 24, 2020

  • I would suggest using random.uniform() instead of random.random() since some darts might be landed on the edge of the square, but random.random() only generates a random float uniformly in the semi-open range [0.0, 1.0), while random.uniform() generates a random float uniformly in the range [0.0, 1.0].

  • no indentation needed in the if clause.

  • no math.sqrt needed (reduce computational cost). if math.sqrt(x2 + y2) < 1.0 then x2+y2 < 1.0, vice versa.

@ifuchs
Copy link

ifuchs commented Apr 27, 2020

Doesn't this do the same thing without dealing with the square or the x,y coords?

import random
iterations = 1000000
x = 0
for i in range(iterations):
	x+=(1-random.random()**2)**.5
print(4*x/iterations)

@nisarkhanatwork
Copy link

nisarkhanatwork commented Mar 22, 2021

Thank you. Here is a translated SNAP! program version...https://snap.berkeley.edu/project?user=nisar&project=monte_carlo_pi_calculation

@mfriar2
Copy link

mfriar2 commented Apr 1, 2021

Thank you! This helped me understand how to run it with x and y.

@srdinsek
Copy link

srdinsek commented Feb 17, 2022

Here is a slightly faster version.

def square_pi(N):
    # square_pi(100000000) is fast and gives 4 digits. 
    xy = np.random.random((N, 2)) ** 2
    counts = np.sum((xy[:, 0] + xy[:, 1]) <= 1)

    print("pi was approximated at ::",4*counts/N)
    return 4*counts/N

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment