C 언어로 몬테 카를로 방법을 이용한 원주율 (π) 근사

CBeginner
지금 연습하기

소개

이 실험에서는 C 프로그래밍 언어를 사용하여 몬테 카를로 방법을 이용하여 원주율 (π) 의 근사값을 계산하는 방법을 배웁니다. 단위 정사각형 내에서 무작위 점들을 생성한 후, 사분원 내에 포함되는 점들을 세어 π의 근사값을 계산합니다. 마지막으로 계산된 근사값을 출력합니다.

이 실험은 원주율 추정을 위한 몬테 카를로 방법의 핵심 단계, 즉 무작위 점 생성, 사분원 내 점 계산, 전체 점에 대한 사분원 내 점의 비율을 사용하여 근사값 계산을 다룹니다. 이 실험은 C 프로그래밍 언어를 사용하여 미적분학 및 해석 기하학 개념의 실제 응용 사례를 보여줍니다.

단위 정사각형 내 무작위 점 생성

이 단계에서는 C 프로그래밍 언어를 사용하여 단위 정사각형 내 무작위 점을 생성하는 방법을 배우겠습니다. 이는 원주율 (π) 을 근사하는 몬테 카를로 방법의 중요한 부분입니다.

먼저 ~/project 디렉토리에 새로운 C 파일을 만들어 무작위 점 생성을 구현해 봅시다.

cd ~/project
nano random_points.c

이제 무작위 점을 생성하는 코드를 작성해 봅시다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM_POINTS 10000

int main() {
    // 난수 생성기를 초기화합니다.
    srand(time(NULL));

    // 단위 정사각형 내 무작위 점 생성
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        printf("점 %d: (%.4f, %.4f)\n", i + 1, x, y);
    }

    return 0;
}

코드를 자세히 살펴보겠습니다.

  • srand(time(NULL)): 현재 시간으로 난수 생성기를 초기화합니다.
  • (double)rand() / RAND_MAX: 0 과 1 사이의 난수를 생성합니다.
  • 단위 정사각형 (0,0) 에서 (1,1) 사이에 10,000 개의 무작위 점을 생성합니다.

프로그램을 컴파일하고 실행해 봅시다.

gcc random_points.c -o random_points
./random_points

예시 출력:

점 1: (0.7234, 0.5678)
점 2: (0.2345, 0.9876)
...
점 10000: (0.1122, 0.3344)

사분원 내 점 개수 계산 및 π 근사

이 단계에서는 이전 프로그램을 수정하여 사분원 내 점의 개수를 세고 이 정보를 사용하여 원주율 (π) 의 근사값을 계산합니다.

random_points.c 파일을 업데이트해 봅시다.

cd ~/project
nano random_points.c

이전 코드를 다음 구현으로 바꿉니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define NUM_POINTS 100000

int main() {
    // 난수 생성기를 초기화합니다.
    srand(time(NULL));

    int points_inside_circle = 0;

    // 무작위 점을 생성하고 사분원 내 점의 개수를 셉니다.
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // 점이 사분원 내에 있는지 확인합니다.
        if (x*x + y*y <= 1.0) {
            points_inside_circle++;
        }
    }

    // π를 근사합니다.
    double pi_approximation = 4.0 * points_inside_circle / NUM_POINTS;

    printf("총 점 개수: %d\n", NUM_POINTS);
    printf("사분원 내 점 개수: %d\n", points_inside_circle);
    printf("π의 근사값: %.6f\n", pi_approximation);
    printf("실제 π 값:    %.6f\n", M_PI);
    printf("차이:        %.6f\n", fabs(pi_approximation - M_PI));

    return 0;
}

수학 라이브러리와 함께 프로그램을 컴파일합니다.

gcc random_points.c -o random_points -lm
./random_points

예시 출력:

총 점 개수: 100000
사분원 내 점 개수: 78540
π의 근사값: 3.141600
실제 π 값:    3.141593
차이:        0.000007

핵심 변경 사항을 살펴보겠습니다.

  • 정확도를 높이기 위해 점의 개수를 늘렸습니다.
  • 사분원 내 점의 개수를 계산하는 논리를 추가했습니다.
  • 공식: π ≈ 4 * (사분원 내 점 개수) / (총 점 개수) 를 사용했습니다.
  • 실제 π 값과의 비교를 포함했습니다.

근사값 출력

이 마지막 단계에서는 π 근사 프로그램을 개선하여 결과를 출력하는 함수를 만들고 출력 형식을 개선합니다.

random_points.c 파일을 수정해 봅시다.

cd ~/project
nano random_points.c

새로운 출력 함수와 개선된 출력으로 코드를 업데이트합니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define NUM_POINTS 1000000

// 근사 결과를 출력하는 함수
void print_pi_approximation(int total_points, int points_inside_circle) {
    double pi_approximation = 4.0 * points_inside_circle / total_points;

    printf("π 근사 결과\n");
    printf("=====================\n");
    printf("생성된 총 점 개수:        %d\n", total_points);
    printf("사분원 내 점 개수:  %d\n", points_inside_circle);
    printf("근사 π 값:          %.8f\n", pi_approximation);
    printf("실제 π 값:                %.8f\n", M_PI);
    printf("절대 차이:           %.8f\n", fabs(pi_approximation - M_PI));
    printf("근사 정확도:        %.4f%%\n",
           (1 - fabs(pi_approximation - M_PI) / M_PI) * 100);
}

int main() {
    // 난수 생성기를 초기화합니다.
    srand(time(NULL));

    int points_inside_circle = 0;

    // 무작위 점을 생성하고 사분원 내 점의 개수를 셉니다.
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // 점이 사분원 내에 있는지 확인합니다.
        if (x*x + y*y <= 1.0) {
            points_inside_circle++;
        }
    }

    // 근사 결과를 출력합니다.
    print_pi_approximation(NUM_POINTS, points_inside_circle);

    return 0;
}

프로그램을 컴파일하고 실행합니다.

gcc random_points.c -o random_points -lm
./random_points

예시 출력:

π 근사 결과
=====================
생성된 총 점 개수:        1000000
사분원 내 점 개수:  785398
근사 π 값:          3.14159200
실제 π 값:                3.14159265
절대 차이:           0.00000065
근사 정확도:        99.9998%

주요 개선 사항:

  • 전용 함수 print_pi_approximation()를 만들었습니다.
  • 더 나은 정확도를 위해 점의 개수를 1,000,000 으로 늘렸습니다.
  • 더 자세한 출력 형식을 추가했습니다.
  • 근사 정확도 백분율을 포함했습니다.

요약

이 실험에서는 먼저 C 프로그래밍 언어를 사용하여 단위 정사각형 내에서 무작위 점을 생성하는 방법을 배웠습니다. 이는 원주율 (π) 을 근사하는 몬테 카를로 방법의 중요한 부분입니다. 난수 생성기를 현재 시간으로 시드한 후 rand() 함수를 사용하여 단위 정사각형 (0,0) 에서 (1,1) 까지 10,000 개의 무작위 점을 생성했습니다.

다음으로, 프로그램을 수정하여 사분원 내 점의 개수를 세고 이 정보를 사용하여 원주율 (π) 의 근사값을 계산했습니다. 100,000 개의 무작위 점을 생성하고, 이 중 사분원 내에 포함된 점을 확인했습니다. 원 내부 점의 개수와 총 점 개수의 비율을 계산하여 원주율 (π) 의 값을 추정할 수 있었습니다.