Симулятор дартс Монте-Карло

Я пытался создать симулятор дротика, используя симуляцию Монте-Карло в Python 3. До сих пор я написал следующий код:

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))

Однако, когда я запускаю это, я получаю следующее сообщение об ошибке:

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

person Blake McLaughlin    schedule 22.10.2017    source источник
comment
с какой ошибкой вы сталкиваетесь?   -  person Willem Van Onsem    schedule 23.10.2017
comment
n = (input("Enter the number of darts you have. ")) дает вам строку, которую вы, вероятно, захотите преобразовать в int, например: n = int(input("Enter the number of darts you have. "))   -  person UnholySheep    schedule 23.10.2017
comment
TypeError: '‹=' не поддерживается между экземплярами 'int' и 'str'   -  person Blake McLaughlin    schedule 23.10.2017
comment
После того, как я это сделаю, преобразую его в int, я получаю эту ошибку. File Untitled 12.py, строка 18, в ‹module› print(Pi is + 4*(1.*circleval/squareval)) TypeError: должно быть str, а не float   -  person Blake McLaughlin    schedule 23.10.2017


Ответы (3)


Основная причина, по которой это не работает, заключается в том, что:

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

поместит строку в n, мы можем решить это с помощью:

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

и:

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

ожидает строку, но вы ее не предоставляете, мы можем решить это с помощью:

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

Но при этом программа по-прежнему неверна: она выдает 0.773 в качестве вывода для Pi, что явно неверно.

Основная проблема заключается в вашей выборке: вы хотите генерировать числа от -1 до 1, но вы генерируете числа от -1 до 3. В ваших вычислениях расстояний вы затем используете x-1 и y-1, сдвигая их в область от -2 до 2, но это все еще слишком велико. Кроме того, код не очень элегантный.

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))

для n=100000 это дало мне 3.14368 (хотя, конечно, это может варьироваться между несколькими симуляциями).

person Willem Van Onsem    schedule 22.10.2017
comment
@ Блейк Маклафлин, это должен быть принятый ответ, поскольку Виллем также объясняет проблему с реализацией алгоритма. - person Nir Alfasi; 23.10.2017
comment
Да, мой плохой, я только что проверил, я пытался изменить переменную n, чтобы она была циклом for, чтобы я мог иметь длинный диапазон выходных данных для того, чему равно число pi. Извините, что не дал вам кредит сразу, это был мой плохой, спасибо за исправления! - person Blake McLaughlin; 23.10.2017

Две проблемы:

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

должно быть:

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

(поскольку вы хотите рассматривать n как целое число)

и

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

должно быть:

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

Поскольку вы не можете добавить строку к числу

Кроме этого - я не уверен, что расчет правильный - но это будет другой вопрос.

person Nir Alfasi    schedule 22.10.2017
comment
Спасибо, я попробую ввести это в исходный код. - person Blake McLaughlin; 23.10.2017
comment
Это сработало хорошо, спасибо за помощь. Как бы глупо это ни звучало, Ин пытался поставить строку после оператора печати, прежде чем задавать вопрос. Спасибо за исправление alfasin. - person Blake McLaughlin; 23.10.2017

В дополнение к уже выявленным проблемам преобразования строки в целое, вам может показаться проще, если вы установите границы x и y равными [-1,1].
Также рассмотрите возможность использования 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))

Выход:

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

Примечания:
– Вам не нужно отслеживать squareval, вы можете просто использовать n.
– Вы можете использовать векторизованные операции Numpy, чтобы пропустить while-цикл:

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)
person andrew_reece    schedule 22.10.2017