# Monte Carlo method of computing pi
# Toss darts at a dart board (2x2, centered at (0,0)
# The ratio of the darts in the unit circle to all darts is pi/4
#
import random
import math
# Generate a landing position for a dart tossed at
# a 2x2 square with center at (0,0)
# returns: (x, y) co-ordinates of toss
def gentoss():
x = 2*random.random() - 1
y = 2*random.random() - 1
return x, y
# for point x, y, if x^2 + y^2 <= 1, they are in the unit circle
# parameters: x, y: co-ordinates of point
# returns True if so, False if not
def inunitcircle(x, y):
return x ** 2 + y ** 2 <= 1
# function to read and vet user selection
# returns: n, the number of tosses
# NOTE: n must be positive; return -1 to quit
def getinput():
# loop until we get good input
while True:
try:
# get the input and check the type here
n = int(input("number of tosses (EOF to quit): "))
except EOFError: # user wants to quit, so help
n = -1
break
except ValueError: # user didn't enter a number
print("You have to enter a positive n or EOF")
continue
# got an integer
# now check the value we read/were given
if n > 0:
break
# this is bad input, so say so
print("You have to enter a positive n or EOF")
# it's positve to continue, -1 to quit
return n
# main routine: pull it all together
def main():
# get number of tosses
n = getinput()
if n > 0:
# number of darts in unit circle
# nothing thrown yet
h = 0
# now start throwing
for i in range(n):
# toss
x, y = gentoss()
# is it in the circle?
if inunitcircle(x, y):
h += 1
# done! see how well you did ...
print(" number of throws: %8d\t\tapproximation to pi: %9.7f" % (n, 4.0 * h / n))
print(" number of hits: %8d\t\t actual value of pi: %9.7f" % (h, math.pi))
print(" ratio: %8.6f\t\t error: %9.7f" % (h/n, abs(4.0 * h / n - math.pi)))
#
# run the simulation
#
main()