When studying up on interview skills and grinding leetcode problems, this specific problem seemed to be beloved by
a large group of people. It forces us to deeply think about how interconnected mathematics
can be (atleast, that was my experience).
Can you obtain an accurate estimate of pi using only random numbers?
Now,I'm not the first person to complete this problem and I surely won't be the last, however I plan to still walk through
how this problem works and how I went about coding a simple solution. The process described is meant to be applicable
no matter what coding language or software you intend to use.
To start out, we are given our constraints and a goal, using only numbers from 0 to 1
, we have to estimate the value of pi.
Since our range is 0 to 1, lets start with a box, a simple 1 by 1
box.
How does pi relate to a square? Well, it doesn't really, atleast not in any direct sense.
Lets try to add a circle with radius one into our box. Well a circle that big won't fit.
However, one quadrant of that circle will, let's use that.
Now we have separated our 1 unit area into two sections, the space within the circle, and the space outside it.
Because our goal is to estimate pi, let's see where pi is in our scenario.
Using our quarter circle, we know its area will be a quarter of a circle with radius 1.
using A=pi * r^2
, we know that the full circle would be an area of pi
and our quarter would be pi/4
.
So now we can start bringing our pieces togther.
We know that of our two sections in our box, we have an area of pi/4 and an area of whatever
1-(pi/4)
is.
That 1-pi/4 is a lot harder to look at
than 1, so instead, let's say that out of an area of 1, pi/4
amount is within the circle.
This is where some of the thinking comes in.
Say we take one point within the box and check if it is within our pi/4 area of our circle.
We could check this by calculating the distance from the center our point is, basically drawing a line
from the origin to our point.
If the length of that line is greater than the radius of 1 from our circle,
the point will have to be outside our circle. If our line from point to origin is less than our radius of 1,
then our point is within our pi/4 section.
Not very helpful on its own.
Now lets say we asked all of the points in our box if they were within the circle or not.
What would the results look like?
We would end up with about pi/4 of the points being within our circle
because that is how much of the area our circle takes up out of the total.
So if we take that pi/4 points, multiply by 4, we would get pi, right?
So how would we go about "asking" each point if they are within the circle?
Let's start by just asking one.
Say it is within, we now say that 100% of the points are within the circle.
This means that our ratio is 1.0 of the points take up pi/4 amount of space.
Solving this equation for pi means we get pi is equal to 4.
That isn't quite right.
Let's get more data and ask another point.
and another. and another. and another. and so on and so on until
we have asked all the points.
You will see that our first guess of pi=4
, could go from pi=2
, to pi=2.66
, to pi=3
, and so on.
Our solution for pi slowly gets closer and closer to the value we are expecting of 3.14159...
So now we know our process, let's put this into code.
First I set up my box and circle quadrant on my canvas.
Then I set a variable for the amount of points we want to "ask".
The higher the better.
Let's start asking points by traversing a for loop that will ask our desired amount of points.
We determine which point to ask by using our random numbers from 0 to 1.
We get one random number for our x coordinate, and one for our y.
Now we have our point, how does it know if it is within our circle?
We calculate the distance from our point to the origin using the basic distance formula.
sqrt(x^2 + y^2)
Okay so let's say our first point had a distance of 1 or less.
That means we have 1 point inside our circle and we have asked 1 point total.
Let's add variables to keep track of both of those numbers as we ask more points.
Now that we have asked a new point, let's update our solution for pi.
Now that we have our "solution", we either continue asking more points or we decide that we are happy with our
estmate and have asked enough points for their whereabouts.
The embeded p5js frame at the start of the page is what this looks like in action using a maximum of 5000 points.
Feel free to take a look at the code specific for this p5 js generation and try it out yourself!
//Quick visualization of how to estimate Pi
//using only random floats from 0 to 1 and
//basic geometry.
//Made for Pi day 2022
let totalPoints = 0;
let circlePoints = 0;
//sets how many points to use in estimate
const maxPoints = 5000;
//Arrays hold the previous points so each
//draw() call doesn't erase the previous points
let globalX = [];
let globalY = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
//draw the arc of the circle
arc(0,400, 800, 800, -PI / 2, 0);
//add a point until the estimation limit is reached
if(totalPoints < maxPoints){
addPoint();
}else{
noLoop();
}
//plot all the current points
for(let i = 0; i < totalPoints; i++){
point(globalX[i], globalY[i]);
}
strokeWeight(5);
//Adds the text in the top left
rect(0,0, 200, 50, 0);
let currentEstimate = (4 * (circlePoints/totalPoints)).toFixed(7);
text("Total Points: " + totalPoints + " || In Circle: " + circlePoints + "\nCurrent Estimation of Pi: " + currentEstimate,0,10, 300, 50);
//fill(10);
}
function addPoint(){
//generates the random points
let x_val = random(0,1);
let y_val = random(0,1);
//adds the point to the array
globalX.push(x_val*400);
globalY.push(y_val*400);
//checks if the point is in the arc or not
let dist = sqrt(sq(x_val) + sq(y_val));
totalPoints++;
if(dist <= 1){
circlePoints++;
}
}