몬테카를로 시뮬레이션은 반복된 무작위 추출을 이용하여 함수의 값을 수리적으로 근사하는 알고리즘이다.
이를 통해 우리는 파이의 값을 추론할 수 있다.
한 변의 길이가 2인 정사각형 안에 내접하는 반지름이 1인 원이 있다고 생각해 보자.
그러면 원의 넓이는 pi가 될 것이고, 정사각형의 넓이는 4가 될 것이다.
원의 넓이 : 정사각형 넓이 = pi : 4 이므로, 따라서 pi=(원의 넓이)/(정사각형 넓이) *4이다.
점을 많이 찍을수록 정사각형과 원 안에 점이 많이 찍힐 것이므로 자연스레 근삿값도 정확해질 것이다.
이때 시각적으로 보기 위해 터틀그래픽을 이용한다.
기본 준비: 정사각형과 원, x축과 y축을 그린다.
def t_square(x, y, l): #(x,y)를 중점으로 하는 한 변의 길이가 l인 정사각형 그리는 함수
t.pu()
t.goto(x - l / 2, y - l / 2)
t.pd()
for _ in range(4):
t.forward(l)
t.left(90)
def t_circle(x, y, r): #(x,y)를 중점으로하는 반지름의 길이가 r인 원 그리는 함수
t.pu()
t.goto(x, y - r)
t.pd()
t.circle(r)
def t_cross(x, y, l): #(x,y)를 중점으로 하는 한 선분의 길이가 l인 십자 그리는 함수
t.pu()
t.goto(x - l / 2, y)
t.pd()
t.forward(l)
t.pu()
t.goto(x, y + l / 2)
t.right(90)
t.pd()
t.forward(l)
t.left(90)
원안에 찍은 점은 파란색 원의 바깥쪽에 찍은 점은 빨간색으로 나타낸다.
이때 원 안에 찍히는지 판별하는 방법은 여러 가지가 있겠지만 우리가 알고 있는 x좌표와 y좌표로 가장 간단히 구할 수 있는 방법은 원의 방정식이다.
(0,0)을 중점으로 하는 원의 방정식은 x^2 + y^2 = r^2이다. 이는 원의 중점으로부터 반지름만큼 떨어진 거리의 점을 모두 나타낸 것이다. 그렇다면 원 안쪽에 있는 점을 식으로 나타내면 x^2 + y^2 <= r^2이다.
x=0
y=0
r=100 #원의 반지름
l=200 #정사각형 한 변의 길이
t_square(0,0,l)
t_circle(0,0,r)
t_cross(0,0,l)
red_dots=0 #빨간색 점의 갯수
blue_dots=0 #파란색 점의 갯수
for _ in range(10000): #시행 횟수가 많아질수록 값이 정확해짐.
randx = random.randint(-r, r)
randy = random.randint(-r, r)
t.pu()
t.goto(randx, randy)
t.pd()
if(math.sqrt(randx**2 + randy**2) <= r): #원의 방정식
t.dot(3,'blue')
blue_dots+=1
else:
t.dot(3,'red')
red_dots+=1
파란 점의 개수와 (파란 점 개수)+(빨간 점 개수)의 비는 원의 넓이와 정사각형의 넓이의 비와 근사하다.
따라서 우리는 pi근사값을 구할 수 있다.
estimated_pi = (blue_dots / (blue_dots+red_dots)) * 4
print(f"pi 근사값: {estimated_pi}")
전체코드:
import math
import random
import turtle
t = turtle.Turtle()
t.shape('turtle')
def t_square(x, y, l):
t.pu()
t.goto(x - l / 2, y - l / 2)
t.pd()
for _ in range(4):
t.forward(l)
t.left(90)
def t_circle(x, y, r):
t.pu()
t.goto(x, y - r)
t.pd()
t.circle(r)
def t_cross(x, y, l):
t.pu()
t.goto(x - l / 2, y)
t.pd()
t.forward(l)
t.pu()
t.goto(x, y + l / 2)
t.right(90)
t.pd()
t.forward(l)
t.left(90)
x=0
y=0
r=100
l=200
t_square(0,0,l)
t_circle(0,0,r)
t_cross(0,0,l)
red_dots=0 #빨간색 점의 갯수
blue_dots=0 #파란색 점의 갯수
for _ in range(10000): #시행 횟수가 많아질수록 값이 정확해짐.
randx = random.randint(-r, r)
randy = random.randint(-r, r)
t.pu()
t.goto(randx, randy)
t.pd()
if(math.sqrt(randx**2 + randy**2) <= r): #원의 방정식
t.dot(3,'blue')
blue_dots+=1
else:
t.dot(3,'red')
red_dots+=1
estimated_pi = (blue_dots / (blue_dots+red_dots)) * 4
print(f"pi 근사값: {estimated_pi}")
'Python' 카테고리의 다른 글
Python; 리스트 함축 (List Comprehension) (0) | 2024.06.09 |
---|---|
Python; 터틀그래픽 10개의 랜덤한 원 그리기 (2) | 2024.05.21 |
python; 정적분을 활용하여 원뿔대 부피 구하기 (0) | 2023.03.01 |
python; 2차 정방행렬(2X2)의 고윳값(고유치) 구하기 (0) | 2022.10.28 |
python; 근의공식 구현하기 (0) | 2022.10.28 |
댓글