Utilizar Simulação de Monte Carlo para Probabilidade em C

CBeginner
Pratique Agora

Introdução

Neste laboratório, exploraremos como utilizar a simulação de Monte Carlo para estimar probabilidades em programação C. Começaremos definindo um experimento aleatório simples, como o lançamento de uma moeda, e, em seguida, executaremos múltiplos ensaios para contar o número de resultados bem-sucedidos. Finalmente, calcularemos a probabilidade estimada dividindo o número de sucessos pelo número total de ensaios. Este laboratório fornece uma introdução prática aos conceitos fundamentais de probabilidade e combinatória usando C, habilidades essenciais para análise de dados e tomada de decisões.

Definir um Experimento Aleatório

Neste passo, exploraremos como definir um experimento aleatório usando a simulação de Monte Carlo em C. Um experimento aleatório é um processo com resultados incertos que pode ser simulado usando técnicas de probabilidade.

Compreendendo Experimentos Aleatórios

Vamos criar um programa C simples para demonstrar um experimento aleatório básico: a simulação do lançamento de uma moeda.

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

#define NUM_TRIALS 1000

int main() {
    // Semente o gerador de números aleatórios
    srand(time(NULL));

    // Contagem de caras
    int heads_count = 0;

    // Simular lançamentos de moeda
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Gerar um número aleatório 0 ou 1
        int flip = rand() % 2;

        // Contar caras
        if (flip == 0) {
            heads_count++;
        }
    }

    // Calcular a probabilidade de caras
    double probability = (double)heads_count / NUM_TRIALS;

    printf("Experimento de Lançamento de Moeda:\n");
    printf("Total de Ensaios: %d\n", NUM_TRIALS);
    printf("Contagem de Caras: %d\n", heads_count);
    printf("Probabilidade Estimada de Caras: %.2f\n", probability);

    return 0;
}

Exemplo de saída:

Experimento de Lançamento de Moeda:
Total de Ensaios: 1000
Contagem de Caras: 502
Probabilidade Estimada de Caras: 0.50

Conceitos-chave Explicados

  1. Geração de Números Aleatórios:

    • srand(time(NULL)) sementeia o gerador de números aleatórios
    • rand() % 2 gera 0 ou 1 com probabilidade igual
  2. Design do Experimento:

    • Definimos o lançamento de uma moeda como nosso experimento aleatório
    • Executamos múltiplos ensaios (1000 neste caso)
    • Contamos o número de resultados bem-sucedidos (caras)
  3. Estimação da Probabilidade:

    • Probabilidade = (Número de Resultados Bem-Sucedidos) / (Número Total de Ensaios)
    • Neste caso, esperamos uma probabilidade próxima de 0,5 para caras

Compilar e Executar o Programa

## Criar o arquivo de origem
nano ~/project/coin_flip_experiment.c

## Compilar o programa
gcc ~/project/coin_flip_experiment.c -o ~/project/coin_flip_experiment

## Executar o experimento
~/project/coin_flip_experiment

Exemplo de saída de compilação e execução:

## Compilação
gcc ~/project/coin_flip_experiment.c -o ~/project/coin_flip_experiment

## Execução
~/project/coin_flip_experiment
Experimento de Lançamento de Moeda:
Total de Ensaios: 1000
Contagem de Caras: 502
Probabilidade Estimada de Caras: 0.50

Executar Muitos Ensaios Aleatórios e Contar Sucessos

Neste passo, expandiremos nossa simulação de Monte Carlo executando múltiplos ensaios aleatórios e contando com precisão os resultados bem-sucedidos. Demonstraremos isso por meio de um experimento de probabilidade mais complexo: estimar π (pi) usando a geração de pontos aleatórios.

Método de Monte Carlo para Estimativa de π

Usaremos uma abordagem geométrica para estimar π gerando pontos aleatórios dentro de um quadrado que contém um quarto de círculo.

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

#define NUM_TRIALS 100000

int main() {
    // Semente o gerador de números aleatórios
    srand(time(NULL));

    // Contadores para pontos totais e pontos internos
    int total_points = 0;
    int points_inside_circle = 0;

    // Executar múltiplos ensaios
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Gerar coordenadas x e y aleatórias entre 0 e 1
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // Verificar se o ponto está dentro do quarto de círculo
        if (sqrt(x*x + y*y) <= 1.0) {
            points_inside_circle++;
        }
        total_points++;
    }

    // Estimar π
    double pi_estimate = 4.0 * points_inside_circle / total_points;

    printf("Experimento de Estimativa de π:\n");
    printf("Pontos Totais: %d\n", total_points);
    printf("Pontos Dentro do Círculo: %d\n", points_inside_circle);
    printf("π Estimado: %.6f\n", pi_estimate);
    printf("π Real:    %.6f\n", M_PI);

    return 0;
}

Compilar e Executar o Experimento

## Criar o arquivo de origem
nano ~/project/pi_estimation.c

## Compilar o programa (observe o link da biblioteca matemática)
gcc ~/project/pi_estimation.c -o ~/project/pi_estimation -lm

## Executar o experimento
~/project/pi_estimation

Exemplo de saída:

Experimento de Estimativa de π:
Pontos Totais: 100000
Pontos Dentro do Círculo: 78540
π Estimado: 3.141600
π Real:    3.141593

Conceitos-chave Explicados

  1. Múltiplos Ensaios:

    • Executamos um grande número de ensaios aleatórios (100.000)
    • Cada ensaio gera um ponto aleatório em um quadrado 1x1
  2. Contando Sucessos:

    • Acompanhamos os pontos totais e os pontos dentro do quarto de círculo
    • O sucesso é definido como um ponto que cai dentro do círculo
  3. Estimação da Probabilidade:

    • Probabilidade = (Pontos Bem-Sucedidos) / (Pontos Totais)
    • Multiplicar por 4 para estimar π devido ao método do quarto de círculo

Técnicas Importantes

  • (double)rand() / RAND_MAX gera um decimal aleatório entre 0 e 1
  • sqrt(x*x + y*y) calcula a distância da origem
  • Um grande número de ensaios melhora a precisão da estimativa

Estimar Probabilidade = Sucessos/Ensaios

Neste passo final, demonstraremos como calcular a probabilidade analisando a razão entre resultados bem-sucedidos e ensaios totais em um cenário mais prático.

Experimento de Probabilidade de Lançamento de Dados

Simularemos o lançamento de dois dados e calcularemos a probabilidade de obter uma soma específica (por exemplo, soma de 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() {
    // Semente o gerador de números aleatórios
    srand(time(NULL));

    // Contadores para lançamentos totais e lançamentos bem-sucedidos
    int total_rolls = 0;
    int successful_rolls = 0;

    // Executar múltiplos ensaios
    for (int i = 0; i < NUM_TRIALS; i++) {
        // Lançar dois dados
        int die1 = roll_die();
        int die2 = roll_die();

        // Verificar se a soma corresponde ao alvo
        if (die1 + die2 == TARGET_SUM) {
            successful_rolls++;
        }
        total_rolls++;
    }

    // Calcular a probabilidade
    double probability = (double)successful_rolls / total_rolls;

    printf("Experimento de Probabilidade de Lançamento de Dados:\n");
    printf("Soma Alvo: %d\n", TARGET_SUM);
    printf("Lançamentos Totais: %d\n", total_rolls);
    printf("Lançamentos Bem-Sucedidos: %d\n", successful_rolls);
    printf("Probabilidade Estimada: %.4f\n", probability);

    // Probabilidade teórica para comparação
    printf("Probabilidade Teórica: %.4f\n", 1.0/6);

    return 0;
}

Compilar e Executar o Experimento

## Criar o arquivo de origem
nano ~/project/dice_probability.c

## Compilar o programa
gcc ~/project/dice_probability.c -o ~/project/dice_probability

## Executar o experimento
~/project/dice_probability

Exemplo de saída:

Experimento de Probabilidade de Lançamento de Dados:
Soma Alvo: 7
Lançamentos Totais: 100000
Lançamentos Bem-Sucedidos: 16644
Probabilidade Estimada: 0.1664
Probabilidade Teórica: 0.1667

Conceitos-chave Explicados

  1. Cálculo de Probabilidade:

    • Probabilidade = (Número de Resultados Bem-Sucedidos) / (Número Total de Ensaios)
    • Neste caso: Lançamentos Bem-Sucedidos / Lançamentos Totais
  2. Simulação de Monte Carlo:

    • Um grande número de ensaios (100.000) fornece uma estimativa precisa
    • A probabilidade simulada corresponde de perto à probabilidade teórica
  3. Aleatoriedade e Precisão:

    • srand(time(NULL)) garante sequências aleatórias diferentes
    • Mais ensaios aumentam a precisão da estimativa

Interpretação da Probabilidade

  • A probabilidade estimada (0,1664) está muito próxima da probabilidade teórica (1/6 ≈ 0,1667)
  • Demonstra como o método de Monte Carlo pode estimar probabilidades

Resumo

Neste laboratório, aprendemos como definir um experimento aleatório usando simulação de Monte Carlo em C. Criamos uma simulação simples de lançamento de moeda para demonstrar os conceitos-chave. Primeiro, semeamos o gerador de números aleatórios e simulamos lançamentos de moeda, contando o número de resultados bem-sucedidos (caras). Em seguida, estimamos a probabilidade de caras dividindo o número de resultados bem-sucedidos pelo número total de ensaios. A saída mostrou que a probabilidade estimada estava próxima do valor esperado de 0,5 para um lançamento justo de moeda.