Приближение числа π методом Монте-Карло на C

CBeginner
Практиковаться сейчас

Введение

В этом лабораторном практикуме мы изучим, как приблизить значение π с помощью метода Монте-Карло на языке программирования C. Мы начнём с генерации случайных точек внутри единичного квадрата, затем подсчитаем количество точек, попадающих внутрь четверти окружности, чтобы вычислить приближение π. Наконец, мы выведем вычисленное приближение.

Лабораторная работа охватывает ключевые этапы метода Монте-Карло для оценки π, включая генерацию случайных точек, подсчёт точек внутри четверти окружности и использование отношения точек внутри к общему числу точек для вычисления приближения. Этот практикум демонстрирует практическое применение концепций исчисления и аналитической геометрии на языке программирования C.

Генерация случайных точек в единичном квадрате

В этом шаге мы научимся генерировать случайные точки внутри единичного квадрата с помощью языка программирования C, что является важной частью метода Монте-Карло для приближения значения π.

Сначала создадим новый файл C в каталоге ~/project для реализации генерации случайных точек:

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
  • Мы генерируем 10 000 случайных точек в единичном квадрате (0,0) до (1,1)

Компилируем и запускаем программу:

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, что является ключевым элементом метода Монте-Карло для приближённого вычисления значения π. Мы инициализировали генератор случайных чисел текущим временем и сгенерировали 10 000 случайных точек в единичном квадрате (0,0) до (1,1) с помощью функции rand().

Затем мы модифицировали программу, чтобы подсчитывать точки внутри четверти окружности и использовать эту информацию для приближения значения π. Мы сгенерировали 100 000 случайных точек и проверили, какие из них попали внутрь четверти окружности. Вычислив отношение точек внутри окружности к общему количеству точек, мы смогли оценить значение π.