Skip to content

Colin Webb

Simple Monte Carlo Simulation in Rust

Monte Carlo simulations are often used model the probability of different outcomes. They work by generating random values, passing them into a model, and then averaging the results.

The simplest Monte Carlo simulation, and a great way to start, is by using the technique to estimate the value of Pi.

I first did this back in University, albeit using C rather than Rust.


The equation for a circle, centred around the origin is:

$$ x^2 + y^2 = R^2$$

If we put that circle inside a square, and constrain it so that the maximum R is 1, then

$$ x^2 + y^2 = 1 $$

and the area of that square will be $$4r^2$$

More generally,

$$ CircleArea / SquareArea = \Pi r^2 / 4r^2 $$

$$ CircleArea / SquareArea = \Pi / 4 $$

$$ \Pi = 4 (CircleArea / SquareArea) $$

So, to estimate Pi we can generate random values for x and y, between 0 and 1.

Every point will fall inside the square, but only some will fall inside the circle. If we keep a tally of how many points we generate, and work out a ratio of ones that fall inside the circle we can then get an estimate of Pi.

For a more visual description, checkout this YouTube short video (1min).

Time for Rust

Using the rand crate, we can simply generate random values, and work out if the point lies within our circle.

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let total_points = 1_000_000;
    let mut points_inside_circle = 0;

    for _ in 0..total_points {
        let x: f64 = rng.gen();
        let y: f64 = rng.gen();

        if x * x + y * y <= 1.0 {
            points_inside_circle += 1;
        }
    }

    let pi_estimate = 4.0 * (points_inside_circle as f64) / (total_points as f64);

    println!("Estimated Pi = {}", pi_estimate);
}

If you keep in mind that we're aiming at 3.14159265, the simulation quickly reaches two, three and four decimal points correctly.

Past that point, calculating Pi using this method becomes computationally expensive!


Number of PointsPi Estimate
1M3.14256
10M3.14155
100M3.14156
1B3.14158
10B3.14159