본문 바로가기

프로젝트/시각화

[Python] 몬테카를로 방법을 이용하여 원주율, 파이(π)값 구하기

오늘은 몬테카를로 방법을 이용하여 원주율, 파이(π)의 값을 구해보도록 하겠습니다.

 

몬테카를로 방법이란 무작위 추출된 난수를 이용하여 모델(함수)을 구하는 알고리즘을 부르는 용어입니다.

 

몬테카를로 방법은 금융, 물리학 등의 다양한 학문에서 사용됩니다.

 

2차 세계대전 중의 핵무기 개발 프로그램인 맨해튼 계획에 사용되었고 "몬테카를로 방법"이라는 이름 또한 맨해튼 계획 중에 붙여졌습니다.

 

"몬테카를로"는 모나코의 유명한 도박의 도시인데 "몬테카를로 방법"의 무작위성과 연관이 있어 이 이름이 지금까지 내려져오고 있습니다.

 

이제부터 "몬테카를로 방법"의 가장 대표적인 예시인 원주율, 파이(π) 값 구하기 프로젝트를 시작합니다!

 

 

난수 생성


import random  #1
import matplotlib.pyplot as plt  #2

n = 100  #3
x_list = []  #4
y_list = []  #5

for _ in range(n):  #6  
    x = random.random()  #7
    y = random.random()  #8
    x_list.append(x)  #9
    y_list.append(y)  #10
    
plt.figure(figsize=(10,10))  #11
plt.scatter(x_list, y_list)  #12
plt.title(f"n={n}")  #13
plt.show()  #14
  1. 무작위적인 값을 제공해주는 "random" 모듈을 가져옵니다.
  2. 그래프를 그리는 것을 도와주는 "pyplot" 모듈을 가져옵니다.
  3. 난수를 100개로 설정합니다.
  4. "x_list"를 생성합니다.
  5. "y_list"를 생성합니다.
  6. n번 반복하는 "for문"을 제작합니다. 값을 무시하고 싶을 때 언더바("_")를 사용하는 경우가 많습니다.
  7. 0과 1사이의 무작위 값을 "x" 변수에 저장합니다.
  8. 0과 1사이의 무작위 값을 "y" 변수에 저장합니다.
  9. "x"를 "x_list"에 추가합니다.
  10. "y"를 "y_list"에 추가합니다.
  11. 가로 10, 세로 10인 그래프를 생성합니다.
  12. "x_list"가 가로축인, "y_list"가 세로축인 산포도를 생성합니다.
  13. 그래프의 제목을 "f스트링"을 사용하여 "n=100"으로 설정합니다. 
  14. 그래프를 보여줍니다.

 

출력 결과는 다음과 같습니다.

출력 결과

100개의 무작위의 추출된 난수가 그래프 위에 표시되어 있는 것을 확인할 수 있습니다.

 

난수를 더 추가하고 싶다면 이렇게 "n"변수의 숫자를 키워주시면 됩니다.

import random
import matplotlib.pyplot as plt

n = 10000
x_list = []
y_list = []

for _ in range(n):
    x = random.random()
    y = random.random()
    x_list.append(x)
    y_list.append(y)
    
plt.figure(figsize=(10,10))
plt.scatter(x_list, y_list)
plt.title(f"n={n}")
plt.show()

 

출력 결과는 다음과 같습니다.

출력 결과

이제는 난수 그래프를 가지고 원의 넓이를 구해봅시다.

 

 

원의 넓이 구하기


위에서 우리가 구한 정사각형의 면적은 "1"입니다.

 

반지름이 1인 원을 4등분 한 원의 면적은 "π/4"입니다.

 

원점(0, 0)에서 특정 점까지의 거리는 피타고라스 정리에 의해 $$\sqrt{x^2+y^2}$$ 로 표시됩니다. 

 

위의 내용을 바탕으로 원점에서 특정 점까지의 거리가 1 이하면 원 이내에 있다는 것을 알 수 있습니다.

 

원의 넓이는 원점과의 거리가 1이하인 점들의 개수를 전체 점들의 개수로 나누어 구할 수 있습니다. 

 

이를 사용하여 원 내부의 점들을 빨간색으로 표시해봅시다. 

import random
import matplotlib.pyplot as plt
import numpy as np  #1

n = 10000
x_list = []
y_list = []
circle_x = []
circle_y = []
for _ in range(n):
    x = random.random()
    y = random.random()
    x_list.append(x)
    y_list.append(y)

    if np.sqrt(x ** 2 + y ** 2) <= 1:  #2
        circle_x.append(x)  #3
        circle_y.append(y)  #4
        
plt.figure(figsize=(10,10))
plt.scatter(x_list, y_list)
plt.scatter(circle_x, circle_y, c='r')  #5
area = len(circle_x) / len(x_list)  #6
plt.title(f"n={n}, A={area}")  #7
plt.show()

 

  1. 제곱근 계산을 위해 "numpy" 모듈을 가져옵니다.
  2. "numpy"모듈의 "sqrt"함수는 제곱근 계산을 도와줍니다. 피타고라스 정리를 이용하여 원점에서 특정 점까지의 거리가 1보다 작은 경우의 x값과 y값을 추출합니다.
  3. 위에서 구한 특정 x값을 "circle_x" 리스트에 추가합니다.
  4. 위에서 구한 특정 y값을 "circle_y" 리스트에 추가합니다.
  5. 원의 내부로 특정되는 x값과 y값의 점들을 모두 빨간색으로 표시합니다.
  6. 빨간색으로 표시된 (4등분된) 원의 내부의 넓이는 특정 점들의 개수를 전체 점들의 개수로 나누어 구합니다.
  7. 제목에 f스트링을 사용하여 넓이를 추가합니다.

 

출력 결과는 다음과 같습니다.

출력 결과

 

정사각형의 넓이를 1이라고 볼 때, 원의 넓이는 0.78입니다.

 

물론 시뮬레이션을 할 때마다 다른 난수가 생성되기 때문에 원의 넓이는 약간씩 달라질 수 있습니다.

 

이제는 원주율, 파이(π)값을 구해봅시다.

 

 

원주율, 파이(π)값 구하기


원의 넓이를 구했다면 원주율을 구하는 것은 어렵지 않습니다.

 

원의 넓이를 구하는 공식은 "(반지름)x(반지름)x(π)"입니다.

 

따라서 반지름이 1인 원의 넓이는 "π"이고 위의 그림은 4등분 된 원을 나타내므로 넓이는 "π/4"입니다.

 

그렇다면 위에서 구한 원의 넓이와 π공식으로 구한 원의 넓이를 대조해보면 원주율 값을 구할 수 있겠습니다.

 

import random
import matplotlib.pyplot as plt
import numpy as np

n = 10000
x_list = []
y_list = []
circle_x = []
circle_y = []
for _ in range(n):
    x = random.random()
    y = random.random()
    x_list.append(x)
    y_list.append(y)

    if np.sqrt(x ** 2 + y ** 2) <= 1:
        circle_x.append(x)
        circle_y.append(y)
        
plt.figure(figsize=(10,10))
plt.scatter(x_list, y_list)
plt.scatter(circle_x, circle_y, c='r')
area = len(circle_x) / len(x_list)
pi = area * 4
plt.title(f"n={n}, A={area}, π={pi}")
plt.show()

코드 블록을 보면 "pi"변수가 추가된 것을 볼 수 있습니다.

 

"원의 넓이 = π/4" 이므로 "π = 원의 넓이 x 4"입니다.

 

π값을 구하고 그래프의 제목에도 넣어줍니다.

 

출력 결과는 다음과 같습니다.

출력 결과

원주율, 파이(π) 값은 "3.13~"값이 나왔습니다.

 

하지만, 난수를 키울수록 정확도는 올라갑니다.

 

난수를 100만으로 설정한 후 출력해보겠습니다.

 

출력 결과는 다음과 같습니다.

출력 결과

원주율, 파이(π) 값이 우리가 알고 있는 "3.14"값에 이전보다 가까워진 것을 알 수 있습니다.

 

실제 원주율은 "3.14159~"이기 때문에 위에서 구한 값도 정확하다고 할 수는 없겠습니다.

 

하지만, 난수를 더 크게 설정할수록 실제 원주율 값에 더 가까워질 것입니다.

 


이번 시간에는 몬테카를로 방식을 사용하여 원주율, 파이(π) 값을 구해보았습니다.

 

몬테카를로 방식에 흥미가 간다면 밑의 포스팅 또한 살펴보시면 좋을 것 같습니다.

 

오늘 배운 몬테카를로 방식을 이용하여 경제 모델인 효율적 투자선을 시각화하는 프로젝트입니다.

 

https://bigdata-doctrine.tistory.com/11

 

[Python] (2)올웨더 기반 효율적 투자선 구현 : 수익률, 리스크, 샤프지수 계산

https://bigdata-doctrine.tistory.com/10 [Python] (1)올웨더 기반 효율적 투자선 구현 : 데이터 수집 이번 프로젝트는 효율적 투자선을 파이썬을 통하여 시각화를 해 보는 것입니다. 단순히 효율적 투자선을

bigdata-doctrine.tistory.com

 

 

밑에 오늘 내용을 실습해볼 수 있도록 코랩 링크 남겨놓겠습니다.

 

https://colab.research.google.com/drive/1mDl3hgop0v7rqHNapWHEZO1DeksnFWa9?usp=sharing 

 

몬테카를로 방법을 이용하여 원주율, 파이(π)값 구하기(배포용).ipynb

Colaboratory notebook

colab.research.google.com