From my ancient blogpost. To run it:
- Download these files somewhere on your computer (probably in a fresh directory)
- Run
make
- Watch the pretty numbers
From my ancient blogpost. To run it:
make
FROM python:3.12 | |
ARG PROJECT | |
COPY ./ /opt/${PROJECT} | |
WORKDIR /opt/${PROJECT} |
PROJECT = $(shell basename $(shell pwd)) | |
ID = pikesley/${PROJECT} | |
default: pi | |
build: | |
docker build \ | |
--build-arg PROJECT=${PROJECT} \ | |
--tag ${ID} . | |
run: | |
docker run \ | |
--name ${PROJECT} \ | |
--volume $(shell pwd):/opt/${PROJECT} \ | |
--rm \ | |
--interactive \ | |
--tty \ | |
${ID} bash | |
pi: build | |
docker run \ | |
--name ${PROJECT} \ | |
--volume $(shell pwd):/opt/${PROJECT} \ | |
--rm \ | |
--interactive \ | |
--tty \ | |
${ID} python montecarlo.py |
#!/usr/bin/env python | |
import random | |
import math | |
class Throw: | |
def __init__(self): | |
# generate two random coordinates and work out how far away we are from | |
# the origin | |
self.x = random.random() | |
self.y = random.random() | |
self.distance = self.distance() | |
def distance(self): | |
# the distance from the origin is the hypotenuse of a right-angled | |
# triangle with sides of length and x and y. Pythagoras told us that: | |
# distance = sqrt((x^2) + (y^2)) | |
# which looks like this in python | |
return math.sqrt(self.x**2 + self.y**2) | |
# did we land inside the quadrant? | |
def is_a_hit(self): | |
return self.distance <= 1.0 | |
class MonteCarlo: | |
def __init__(self): | |
self.hits = 0 | |
self.throws = 0 | |
self.pi = 0 | |
def increment(self, throw): | |
self.throws += 1 | |
if throw.is_a_hit(): | |
self.hits += 1 | |
self.calculate_pi() | |
def calculate_pi(self): | |
self.pi = 4 * (float(self.hits) / float(self.throws)) | |
def divides_by(self, number): | |
return float(self.throws) % number == 0 | |
def __repr__(self): | |
return "Throws: %10d, Hits: %10d, Pi: %10f, Actual Pi: %10f" % ( | |
self.throws, | |
self.hits, | |
self.pi, | |
math.pi, | |
) | |
if __name__ == "__main__": | |
import sys | |
try: | |
step = int(sys.argv[1]) | |
except IndexError: | |
step = 1000 | |
m = MonteCarlo() | |
# loop forever | |
while 1: | |
m.increment(Throw()) | |
# only print on every nth iteration | |
if m.divides_by(step): | |
print(m) |