본문 바로가기

Python

(파이썬) 몬테카를로 시뮬레이션을 사용하여 원주율(π) 구하기.

반응형

문제) numpy 이용하여 pi(원주율) 값을 계산하시오.

- 몬테 카를로 방법을 이용하시오.

- 아래 이미지를 참고하여 pi(파이) 값을 출력하시오.


먼저 몬테카를로 시뮬레이션이 무엇인지 이해가 필요하다. 

몬테카를로 방식을 사용하여 원주율을 구하는 원리 
몬테카를로 방식은 '무작위 수(Random number)와 확률로 시뮬레이션을 설계하여 복잡한 문제의 해를 근사적으로 구하는 방법'이다. 


1) 한 변의 길이가 2r인 정사각형을 그리고 그 안에 꼭 맞는 원을 그린다. 원의 반지름은 r.


2) 원의 넓이는 πr**2이며, 정사각형의 넓이는 4r**2이다. 따라서 원의 넓이를 정사각형의 넓이로 나누면 π/4가 된다.


3) 정사각형 내부에 무작위로 점을 찍는다. 그리고 점이 원 안에 찍혔는지 밖에 찍혔는지

확인한다. 점과 중심과의 거리가 원의 반지름과 같거나 작으면 점은 원 안에 찍힌 것이다.


4) 찍은 점의 수가 많아질수록, 전체 점의 수와 원 안에 찍힌 점의 수의 비는 정사각형의 넓이와 원의 넓이의 비에 같아지게 된다. 

 

☞ python 코드

# 몬테카를로 방식을 사용하여 원주율을 구하는 원리 
# 몬테카를로 방식은 '무작위 수(Random number)와 확률로 시뮬레이션을 설계하여 복잡한 문제의 해를 근사적으로 구하는 방법'이다. 
# 1) 한 변의 길이가 2r인 정사각형을 그리고 그 안에 꼭 맞는 원을 그린다. 이때 원의 반지름이 r이다.
# 2) 원의 넓이는 πr**2 이며, 정사각형의 넓이는 4r**2이다. 따라서 원의 넓이를 정사각형의 넓이로 나누면 π/4가 된다.
# 3) 정사각형 내부에 무작위로 점을 찍는다. 그리고 점이 원 안에 찍혔는지 밖에 찍혔는지 확인한다. 점과 중심과의 거리가 원의 반지름과 같거나 작으면 점은 원 안에 찍힌 것이다.
# 4) 찍은 점의 수가 많아질수록, 전체 점의 수와 원 안에 찍힌 점의 수의 비는 정사각형의 넓이와 원의 넓이의 비에 같아지게 된다. 

import random
import matplotlib.pyplot as plt

def estimate_pi(num_points):          # 사용자로부터 점 개수를 입력받아 원주율을 측정하는 함수
    square_points = 0                 # 사각형 내에 찍힌 무작위 점 수 
    circle_points = 0                 # 원 내에 찍힌 무작위 점 수 

    plt.figure(figsize=(5, 5))        # 점 찍힌 부분의 그림 표현
    plt.xlim(0, 1)
    plt.ylim(0, 1)

    for _ in range(num_points):
        x = random.uniform(0, 1)      # 0과 1사이의 무작위 실수를 반환
        y = random.uniform(0, 1)    
        distance = (x**2 + y**2)**0.5 # 범위를 지정해준다. x,y 점과 원점과의 거리
 
        if distance <= 1:             # 만약 x,y와 원점 사이의 거리가 1이하면 원 내에 점을 하나 찍는다. 
            circle_points += 1    
            plt.plot(x, y, 'ro')      # 원에 찍힌 점은 빨간색으로 표시
        else:
            plt.plot(x, y, 'bo')      # 원에 찍히지 않은 점은 파란색으로 표시
        square_points += 1            # 원 바깥에 점을 하나 찍는다. 

    pi = 4 * (circle_points / square_points)            # 원 넓이 / 정사각형의 넓이 = 원에 찍힌 점의 수 / 전체 찍힌 점의 수 = 파이 / 4      // 파이 = (원에 찍힌 점의 수 / 전체 찍힌 점의 수) X 4 
    plt.title("Monte Carlo Method for Pi Estimation")   
    plt.xlabel("X")
    plt.ylabel("Y")
    plt.show()

    return pi

num_points = int(input("찍을 점의 수: "))
A = estimate_pi(num_points)
print("원주율 추정값:", A)

 

찍을 점의 수를 입력해준다. 점의 개수가 많아지면 원주율이 더 정확하게 나온다. 하지만 연산하는데 시간이 오래 걸린다. 

 

입력란에 1000을 입력한다. 

 

1000개 정도 찍으면 원주율이 3.184로 나온다. 원주율은 3.14로 알려져 있다. 점 개수를 늘려봤다. 

 

2500개를 찍으니 원주율 추정값이 3.144로 나온다. 비슷하다. 5000개로 늘려볼까? 

 

5000개로 늘리니 연산 시간이 길어진다. 게다가 추정값이 3.1536으로 2500개보다 떨어지는 모습을 보인다. 

이상해서 계속 반복해봤다. 원주율 추정값이 3.1이 나올 때도 있고, 3.2가 나올 때도 있었다. 

즉, 랜덤하게 점을 찍기 때문에 오차가 계속 생길 수밖에 없다. 

점 개수를 15000개로 늘려도 오차가 생긴다. 

몬테카를로 시뮬레이션은 완벽하게 원주율을 구하는 것이 목표가 아니라 해의 근삿값을 구하는 것이 목표라는 사실을 잊지 말아야겠다. 

반응형