Approximating Pi Using A Circle And A Square

Pi day was a few weeks ago, but I came across this simple approximation of pi recently and decided to put together an example in PHP since it seemed pretty simple.

This approximation of pi centers around a real world example, but we can simulate this using some code.

Let's say you have a dart board that fits inside a square area so that it is flush with the outside of the square. Then you pick someone who is particularly bad at darts and get them to start throwing darts. Record where the darts hit and after a million or so darts you will have a number of darts that hit the board and a number of darts that hit the background.

Using these figures you can work out a (rough) approximation of pi using the following formula.

(dart board hits / (background hits + dart board hits)) * 4

The area of the dart board here is πr2, and the area of the background board is 4r2. The probability that a dart will hit the circle is therefore π/4 (i.e. πr2/4r2), so we can get the original value of pi back by multiplying by 4.

This is an example of a Monte Carlo Simulation, which a technique that predicts possible outcomes of an uncertain event.

Essentially, with enough data points you can build up a picture of the possible outcomes and get a overall picture of what sort of result you will get if you make another move. What we are predicting here is the possibility of a dart hitting the area outside of the dart board, which is close to the value of pi.

To simulate this example in a computer we first need to create the game area, which is a square image that contains a circle in the exact center. The following PHP does this, using the imagefilledrectangle() and imagefilledellipse() to draw the two shapes we are interested in, using different colours.

<?php

$height = 500;
$width = 500;

// Create image.
$img = imagecreatetruecolor($width, $height);

// Set up colours.
$red = imagecolorallocate($img, 255, 0, 0);
$green = imagecolorallocate($img, 0, 255, 0);

// Draw background rectangle.
imagefilledrectangle($img, 0, 0, $width, $height, $red);
// Draw foreground circle.
imagefilledellipse($img, $height / 2, $width /2, $width, $height, $green);

// Generate the image.
imagepng($img, 'pi' . '.png');

// Destroy the image resource.
imagedestroy($img);

This produces the following image.

A red square with a green circle on top, flush with the edges of the background square.

What we need to do now is fun through lots of random points on the image and see what colour they are, using the imagecolorat() function. If the colour is red then we have hit the background, otherwise we assume that we have hit the circle and record a hit to the circle. This method gets around using any actual maths to find out if the point is inside or outside the circle, but that's certainly possible.

We are using the alternative random function mt_rand() here in order to attempt to alleviate the cyclic nature of the PHP native rand() function.

// Set up variables to count the random points.
$circle = 0;
$background = 0;

// Loop x number of times and record where we landed.
for ($i = 0; $i < 10_000_000_000; $i++) {
  $colour = imagecolorat($img, mt_rand(0, $width - 1), mt_rand(0, $height - 1));
  if ($colour === $red) {
    // Record a hit on the background.
    $background++;
  } else {
    // Record a hit on the circle.
    $circle++;
  }
}

Using the results of this loop we can print out the results and make the final calculation like this.

// Report on the findings.
echo 'Circle: ' . $circle . PHP_EOL;
echo 'Background: ' . $background . PHP_EOL;
echo 'Ratio: ' . (($circle/($background+$circle))*4) . PHP_EOL;

With a 10 billion (10,000,000,000) points this takes a few minutes to run and produces the following output.

Circle: 7868623953
Background: 2131376047
Ratio: 3.1474495812

Well, it's close, but not exactly a good approximation. I certainly wouldn't use this technique to calculate the actual value of pi as it would take a very long time and not produce a useful result.

Of course, with this approximation the larger the image and the number of points, the better the approximation. With 10 billion points the script took a little over 30 minutes to complete on my computer so setting the value higher would take much longer and couldn't give decent results.

If I just alter the size of the original image to be 10,000 x 10,000 and run the simulation with just 10 million points I saw pi worked out to be 3.1417928. This is a closer value to pi, but it was more of an artifact of the randomness of the simulation.

Pi appears in all sorts of unusual places, although this isn't necessarily one of them as it does involve circles. What are your favorite approximations of pi? Let me know in the comments below.

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
15 + 5 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.