Использование моделирования Монте-Карло для оценки вероятности на C

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

Введение

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

Определение случайного эксперимента

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

Понимание случайных экспериментов

Давайте создадим простую программу на C, чтобы продемонстрировать базовый случайный эксперимент: моделирование подбрасывания монеты.

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

#define NUM_TRIALS 1000

int main() {
    // Инициализация генератора случайных чисел
    srand(time(NULL));

    // Счётчик выпадений орла
    int heads_count = 0;

    // Моделирование подбрасываний монеты
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Генерация случайного числа 0 или 1
        int flip = rand() % 2;

        // Подсчёт выпадений орла
        if (flip == 0) {
            heads_count++;
        }
    }

    // Расчёт вероятности выпадения орла
    double probability = (double)heads_count / NUM_TRIALS;

    printf("Эксперимент с подбрасыванием монеты:\n");
    printf("Общее количество испытаний: %d\n", NUM_TRIALS);
    printf("Количество выпадений орла: %d\n", heads_count);
    printf("Оценённая вероятность выпадения орла: %.2f\n", probability);

    return 0;
}

Пример вывода:

Эксперимент с подбрасыванием монеты:
Общее количество испытаний: 1000
Количество выпадений орла: 502
Оценённая вероятность выпадения орла: 0.50

Объяснение ключевых понятий

  1. Генерация случайных чисел:

    • srand(time(NULL)) инициализирует генератор случайных чисел
    • rand() % 2 генерирует 0 или 1 с равной вероятностью
  2. Проектирование эксперимента:

    • Мы определяем подбрасывание монеты как наш случайный эксперимент
    • Выполняем множество испытаний (1000 в данном случае)
    • Подсчитываем количество успешных исходов (выпадение орла)
  3. Оценка вероятности:

    • Вероятность = (Количество успешных исходов) / (Общее количество испытаний)
    • В данном случае мы ожидаем вероятность около 0,5 для выпадения орла

Компиляция и запуск программы

## Создайте исходный файл
nano ~/project/coin_flip_experiment.c

## Скомпилируйте программу
gcc ~/project/coin_flip_experiment.c -o ~/project/coin_flip_experiment

## Запустите эксперимент
~/project/coin_flip_experiment

Пример компиляции и вывода:

## Компиляция
gcc ~/project/coin_flip_experiment.c -o ~/project/coin_flip_experiment

## Выполнение
~/project/coin_flip_experiment
Эксперимент с подбрасыванием монеты:
Общее количество испытаний: 1000
Количество выпадений орла: 502
Оценённая вероятность выпадения орла: 0.50

Выполнение множества случайных испытаний и подсчёт успехов

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

Метод Монте-Карло для оценки π

Мы воспользуемся геометрическим подходом для оценки π, генерируя случайные точки внутри квадрата, содержащего четверть окружности.

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

#define NUM_TRIALS 100000

int main() {
    // Инициализация генератора случайных чисел
    srand(time(NULL));

    // Счётчики для общего количества точек и точек внутри круга
    int total_points = 0;
    int points_inside_circle = 0;

    // Выполнение множества испытаний
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Генерация случайных координат x и y между 0 и 1
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // Проверка, находится ли точка внутри четверти круга
        if (sqrt(x*x + y*y) <= 1.0) {
            points_inside_circle++;
        }
        total_points++;
    }

    // Оценка π
    double pi_estimate = 4.0 * points_inside_circle / total_points;

    printf("Эксперимент по оценке π:\n");
    printf("Общее количество точек: %d\n", total_points);
    printf("Точек внутри круга: %d\n", points_inside_circle);
    printf("Оценённое значение π: %.6f\n", pi_estimate);
    printf("Фактическое значение π:    %.6f\n", M_PI);

    return 0;
}

Компиляция и запуск эксперимента

## Создайте исходный файл
nano ~/project/pi_estimation.c

## Скомпилируйте программу (обратите внимание на подключение математической библиотеки)
gcc ~/project/pi_estimation.c -o ~/project/pi_estimation -lm

## Запустите эксперимент
~/project/pi_estimation

Пример вывода:

Эксперимент по оценке π:
Общее количество точек: 100000
Точек внутри круга: 78540
Оценённое значение π: 3.141600
Фактическое значение π:    3.141593

Объяснение ключевых понятий

  1. Множество испытаний:

    • Мы выполняем большое количество случайных испытаний (100 000)
    • Каждое испытание генерирует случайную точку в квадрате 1x1
  2. Подсчёт успехов:

    • Отслеживаем общее количество точек и количество точек внутри четверти круга
    • Успех определяется как попадание точки внутрь круга
  3. Оценка вероятности:

    • Вероятность = (Успешные точки) / (Общее количество точек)
    • Умножение на 4 для оценки π из-за метода четверти круга

Важные техники

  • (double)rand() / RAND_MAX генерирует случайное десятичное число между 0 и 1
  • sqrt(x*x + y*y) вычисляет расстояние от начала координат
  • Большое количество испытаний улучшает точность оценки

Оценка вероятности = успехи/испытания

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

Эксперимент по вероятности броска двух игральных костей

Мы смоделируем бросок двух игральных костей и вычислим вероятность получения определённой суммы (например, сумма 7).

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

#define NUM_TRIALS 100000
#define TARGET_SUM 7

int roll_die() {
    return rand() % 6 + 1;
}

int main() {
    // Инициализация генератора случайных чисел
    srand(time(NULL));

    // Счётчики для общего количества бросков и успешных бросков
    int total_rolls = 0;
    int successful_rolls = 0;

    // Выполнение множества испытаний
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Бросок двух костей
        int die1 = roll_die();
        int die2 = roll_die();

        // Проверка, соответствует ли сумма целевому значению
        if (die1 + die2 == TARGET_SUM) {
            successful_rolls++;
        }
        total_rolls++;
    }

    // Вычисление вероятности
    double probability = (double)successful_rolls / total_rolls;

    printf("Эксперимент по вероятности броска костей:\n");
    printf("Целевая сумма: %d\n", TARGET_SUM);
    printf("Общее количество бросков: %d\n", total_rolls);
    printf("Успешных бросков: %d\n", successful_rolls);
    printf("Оценённая вероятность: %.4f\n", probability);

    // Теоретическая вероятность для сравнения
    printf("Теоретическая вероятность: %.4f\n", 1.0/6);

    return 0;
}

Компиляция и запуск эксперимента

## Создайте исходный файл
nano ~/project/dice_probability.c

## Скомпилируйте программу
gcc ~/project/dice_probability.c -o ~/project/dice_probability

## Запустите эксперимент
~/project/dice_probability

Пример вывода:

Эксперимент по вероятности броска костей:
Целевая сумма: 7
Общее количество бросков: 100000
Успешных бросков: 16644
Оценённая вероятность: 0.1664
Теоретическая вероятность: 0.1667

Объяснение ключевых понятий

  1. Вычисление вероятности:

    • Вероятность = (Количество успешных исходов) / (Общее количество испытаний)
    • В данном случае: Успешные броски / Общее количество бросков
  2. Моделирование Монте-Карло:

    • Большое количество испытаний (100 000) обеспечивает точную оценку
    • Моделируемая вероятность близка к теоретической вероятности
  3. Случайность и точность:

    • srand(time(NULL)) гарантирует различные случайные последовательности
    • Большее количество испытаний увеличивает точность оценки

Интерпретация вероятности

  • Оценённая вероятность (0,1664) очень близка к теоретической вероятности (1/6 ≈ 0,1667)
  • Демонстрирует, как метод Монте-Карло может оценивать вероятности

Резюме

В этом лабораторном практикуме мы изучили, как определить случайный эксперимент с помощью моделирования Монте-Карло на языке C. Мы создали простую симуляцию подбрасывания монеты, чтобы продемонстрировать ключевые понятия. Сначала мы инициализировали генератор случайных чисел и смоделировали подбрасывания монеты, подсчитывая количество успешных исходов (орлов). Затем мы оценили вероятность выпадения орла, разделив количество успешных исходов на общее количество испытаний. Результат показал, что оценённая вероятность близка к ожидаемому значению 0,5 для честной монеты.