Blake McLaughlin
Blake McLaughlin

Reputation: 91

Monte Carlo dart simulator

I've been trying to make a dart simulator using the Monte Carlo simulation in Python 3. So far, I have written the following code:

import random
import math

n = (input("Enter the number of darts you have. "))
count = 1
circleval = 0
squareval = 0
while count <= n:
    y = 2*random.random()*2-1
    x = 2*random.random()*2-1
    if math.sqrt((x-1)**2+(y-1)**2)<=1:
        circleval+=1
        squareval+=1
    else:
        squareval+=1
    count+=1

print("Pi is " + 4*(1.*circleval/squareval))

However, when I run this I reccive the following error message:

TypeError: '<=' not supported between instances of 'int' and 'str'

Upvotes: 1

Views: 1475

Answers (3)

andrew_reece
andrew_reece

Reputation: 21284

In addition to the string-to-int issues already identified, you might find this simpler if you set your x and y bounds to [-1,1].
Also, consider using Numpy:

import numpy as np

n = int(input("Enter the number of darts you have. "))
count = 1
circleval = 0
squareval = 0
while count <= n:
    y = np.random.uniform(low=-1, high=1)
    x = np.random.uniform(low=-1, high=1)
    if np.sqrt(x**2 + y**2) <= 1:
        circleval+=1
        squareval+=1
    else:
        squareval+=1
    count+=1

print("Pi is", 4*(1.*circleval/squareval))

Output:

Enter the number of darts you have. 1000000
Pi is 3.142168

Notes:
- You don't need to keep track of squareval, you can just use n.
- You can use Numpy's vectorized operations to skip the while-loop:

area = 4
n = int(input("Enter the number of darts you have. "))

X = np.random.uniform(low=-1, high=1, size=n)  
Y = np.random.uniform(low=-1, high=1, size=n)   

dist = np.sqrt(X**2+Y**2);  

in_circle = np.sum(dist < 1.0)

print("Pi is", area * in_circle/n)

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477607

The main reason why this does not work is because:

n = (input("Enter the number of darts you have. "))

will put a string into n, we can solve this with:

n = int(input("Enter the number of darts you have. "))

and:

print("Pi is " + 4*(1.*circleval/squareval))

expects a string, but you do not provide one, we can solve this with:

print("Pi is " + str(4*(1.*circleval/squareval)))

But that being said, the program is still incorrect: it gives 0.773 as output for Pi, which is clearly wrong.

The main problem is your sampling: you want to generate numbers between -1 and 1, but you generate numbers between -1 and 3. In your distance computations, you then use x-1 and y-1 shifting it to the -2 to 2 domain, but that is still too large. Furthermore the code not very elegant.

from random import random

n = int(input("Enter the number of darts you have. "))
c = 0
for i in range(n):
    x = 2*random()-1
    y = 2*random()-1
    if x*x + y*y <= 1:
        c += 1
print("Pi is %s" % (4.0*c/n))

for n=100000, this has given me 3.14368 (although it might vary of course between several simulations).

Upvotes: 2

Nir Alfasi
Nir Alfasi

Reputation: 53545

Two issues:

n = input("Enter the number of darts you have. "))

should be:

n = int(input("Enter the number of darts you have. "))

(since you want to treat n as an integer)

and

print("Pi is " + 4*(1.*circleval/squareval))

should be:

print("Pi is " + str(4*(1.*circleval/squareval)))

Since you can't add a string to a number

Other than that - I'm not sure if the calculation is correct - but that would be another issue.

Upvotes: 1

Related Questions