'Fundamental logic error in Monte Carlo Pi Calculation

Im new to programming and decided to take upon the challenge of approximating the value of π using the Monte Carlo simulation with python, below is my code however it does a terrible job of approximating π even after 1,000,000 simulations. Is the way I attempted to do this problem fundamentally flawed?

import math as m
import random
inside_circle = 0
def function(x):
   return m.sqrt(1-(x**2))
def satisfied(x,y):
  global inside_circle
  if y < function(x) or y == function(x):
    inside_circle += 1
  else:
    pass
l1 = []
w1 = []
for i in range(1500000):
  l = [random.random() for _ in range(-1, 1)][0]
  l1.append(l)
  w = [random.random() for _ in range(0, 1)][0]
  w1.append(w)
  satisfied(l,w)
print(inside_circle/1500000*4)


Solution 1:[1]

Your random sampling is not what you think it is and you want

l = 1-2*random.random()
...
w = random.random()

From the binomial distribution variance, the statistical uncertainty of pi for your approach is sqrt(pi(4-pi)/N) since p = pi/4. For N=1e6 events that is about .0016. Running your code with that change 10 times I get a standard deviation of 0.0013 which about what you would expect.

Your approach is not flawed and the observed differences from pi are predicted.

Solution 2:[2]

I mean first of all you should organize and simplify your code a little better.Like

[random.random() for _ in range(-1, 1)][0]

Does essentially just call random.random(), right?

Also try to avoid functions that manipulate global variables that can have nasty side effects so unless you absolutely need them try something else.

For example you could wrap all your stuff in a function:

def simulation(number_of_runs):
    inside = 0
    for i in range(number_of_runs)
        x = random.random()
        y = random.random()        
        if is_in_circle(x,y):
            inside+=1
    return inside/number_of_runs*4

And now you need the function that does the checking (you're put that function before the simulation function):

def is_in_circle(x,y):
    if [condition]:
        return True
    else:
        return False

No need to manipulate any global variables. Now the condition for a circle is that X²+Y²=R (basically a Pythagorean theorem). In your case R is = 1 and so you tried Y = sqrt(1-X²). However you don't need the convoluted:

if y < function(x) or y == function(x):

Python is capable of a <= option. Though I ran the problem (with your code) and it outputs a perfect 3.141912 so what exactly is your problem about?

So no there seems to be no fundamental error in your logic. You guess random numbers between 0 an 1 you look whether they are inside the circle by checking the condition for a circle. You divide the number of points within the circle by the total number of tries and as this is just one quadrant of the circle you multiply by 4 to get pi. And as far as I can see it seems to work.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 possum
Solution 2