TheAlgorithms-Python
67 строк · 2.0 Кб
1import random
2
3
4class Point:
5def __init__(self, x: float, y: float) -> None:
6self.x = x
7self.y = y
8
9def is_in_unit_circle(self) -> bool:
10"""
11True, if the point lies in the unit circle
12False, otherwise
13"""
14return (self.x**2 + self.y**2) <= 1
15
16@classmethod
17def random_unit_square(cls):
18"""
19Generates a point randomly drawn from the unit square [0, 1) x [0, 1).
20"""
21return cls(x=random.random(), y=random.random())
22
23
24def estimate_pi(number_of_simulations: int) -> float:
25"""
26Generates an estimate of the mathematical constant PI.
27See https://en.wikipedia.org/wiki/Monte_Carlo_method#Overview
28
29The estimate is generated by Monte Carlo simulations. Let U be uniformly drawn from
30the unit square [0, 1) x [0, 1). The probability that U lies in the unit circle is:
31
32P[U in unit circle] = 1/4 PI
33
34and therefore
35
36PI = 4 * P[U in unit circle]
37
38We can get an estimate of the probability P[U in unit circle].
39See https://en.wikipedia.org/wiki/Empirical_probability by:
40
411. Draw a point uniformly from the unit square.
422. Repeat the first step n times and count the number of points in the unit
43circle, which is called m.
443. An estimate of P[U in unit circle] is m/n
45"""
46if number_of_simulations < 1:
47raise ValueError("At least one simulation is necessary to estimate PI.")
48
49number_in_unit_circle = 0
50for _ in range(number_of_simulations):
51random_point = Point.random_unit_square()
52
53if random_point.is_in_unit_circle():
54number_in_unit_circle += 1
55
56return 4 * number_in_unit_circle / number_of_simulations
57
58
59if __name__ == "__main__":
60# import doctest
61
62# doctest.testmod()
63from math import pi
64
65prompt = "Please enter the desired number of Monte Carlo simulations: "
66my_pi = estimate_pi(int(input(prompt).strip()))
67print(f"An estimate of PI is {my_pi} with an error of {abs(my_pi - pi)}")
68