Aproximar π Usando un Método de Monte Carlo en C

CBeginner
Practicar Ahora

Introducción

En este laboratorio, aprenderemos a aproximar el valor de π utilizando un método de Monte Carlo en el lenguaje de programación C. Comenzaremos generando puntos aleatorios dentro de un cuadrado unitario, luego contaremos los puntos que caen dentro de un cuarto de círculo para calcular una aproximación de π. Finalmente, imprimiremos la aproximación calculada.

El laboratorio cubre los pasos clave del método de Monte Carlo para estimar π, incluyendo la generación de puntos aleatorios, el conteo de puntos dentro del cuarto de círculo y el uso de la relación entre los puntos dentro y el total de puntos para calcular la aproximación. Este laboratorio proporciona una aplicación práctica de los conceptos de cálculo y geometría analítica en el lenguaje de programación C.

Generar Puntos Aleatorios en un Cuadrado Unitario

En este paso, aprenderemos a generar puntos aleatorios dentro de un cuadrado unitario utilizando el lenguaje de programación C, lo cual es una parte crucial del método de Monte Carlo para aproximar π.

Primero, creemos un nuevo archivo C en el directorio ~/project para implementar la generación de puntos aleatorios:

cd ~/project
nano random_points.c

Ahora, escribamos el código para generar puntos aleatorios:

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

#define NUM_POINTS 10000

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    // Generar puntos aleatorios en el cuadrado unitario
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

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

    return 0;
}

Desglosemos el código:

  • srand(time(NULL)) inicializa el generador de números aleatorios con la hora actual.
  • (double)rand() / RAND_MAX genera un número aleatorio entre 0 y 1.
  • Generamos 10,000 puntos aleatorios en el cuadrado unitario (0,0) a (1,1).

Compile y ejecuta el programa:

gcc random_points.c -o random_points
./random_points

Ejemplo de salida:

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

Contar Puntos Dentro del Cuarto de Círculo y Aproximar π

En este paso, modificaremos nuestro programa anterior para contar los puntos dentro de un cuarto de círculo y utilizar esta información para aproximar el valor de π.

Actualicemos el archivo random_points.c:

cd ~/project
nano random_points.c

Reemplace el código anterior con la siguiente implementación:

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

#define NUM_POINTS 100000

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    int points_inside_circle = 0;

    // Generar puntos aleatorios y contar los que están dentro del cuarto de círculo
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // Comprobar si el punto está dentro del cuarto de círculo
        if (x*x + y*y <= 1.0) {
            points_inside_circle++;
        }
    }

    // Aproximar π
    double pi_approximation = 4.0 * points_inside_circle / NUM_POINTS;

    printf("Puntos totales: %d\n", NUM_POINTS);
    printf("Puntos dentro del cuarto de círculo: %d\n", points_inside_circle);
    printf("Aproximación de π: %.6f\n", pi_approximation);
    printf("Valor real de π:    %.6f\n", M_PI);
    printf("Diferencia:        %.6f\n", fabs(pi_approximation - M_PI));

    return 0;
}

Compile el programa con la biblioteca matemática:

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

Ejemplo de salida:

Puntos totales: 100000
Puntos dentro del cuarto de círculo: 78540
Aproximación de π: 3.141600
Valor real de π:    3.141593
Diferencia:        0.000007

Desglose de los cambios clave:

  • Se incrementó el número de puntos para mejorar la precisión.
  • Se añadió la lógica para contar los puntos dentro del cuarto de círculo.
  • Se utilizó la fórmula: π ≈ 4 * (puntos dentro del círculo) / (puntos totales).
  • Se incluyó la comparación con el valor real de π.

Imprimir la Aproximación

En este paso final, mejoraremos nuestro programa de aproximación de π creando una función para imprimir los resultados y mejorando el formato de la salida.

Modifiquemos el archivo random_points.c:

cd ~/project
nano random_points.c

Actualicemos el código con una nueva función de impresión y una salida mejorada:

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

#define NUM_POINTS 1000000

// Función para imprimir los resultados de la aproximación
void print_pi_approximation(int total_points, int points_inside_circle) {
    double pi_approximation = 4.0 * points_inside_circle / total_points;

    printf("Resultados de la Aproximación de π\n");
    printf("=====================\n");
    printf("Puntos Totales Generados:        %d\n", total_points);
    printf("Puntos Dentro del Cuarto de Círculo:  %d\n", points_inside_circle);
    printf("Valor Aproximado de π:          %.8f\n", pi_approximation);
    printf("Valor Real de π:                %.8f\n", M_PI);
    printf("Diferencia Absoluta:           %.8f\n", fabs(pi_approximation - M_PI));
    printf("Precisión de la Aproximación:    %.4f%%\n",
           (1 - fabs(pi_approximation - M_PI) / M_PI) * 100);
}

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    int points_inside_circle = 0;

    // Generar puntos aleatorios y contar los que están dentro del cuarto de círculo
    for (int i = 0; i < NUM_POINTS; i++) {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // Comprobar si el punto está dentro del cuarto de círculo
        if (x*x + y*y <= 1.0) {
            points_inside_circle++;
        }
    }

    // Imprimir los resultados de la aproximación
    print_pi_approximation(NUM_POINTS, points_inside_circle);

    return 0;
}

Compile y ejecuta el programa:

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

Ejemplo de salida:

Resultados de la Aproximación de π
=====================
Puntos Totales Generados:        1000000
Puntos Dentro del Cuarto de Círculo:  785398
Valor Aproximado de π:          3.14159200
Valor Real de π:                3.14159265
Diferencia Absoluta:           0.00000065
Precisión de la Aproximación:    99.9998%

Mejoras clave:

  • Se creó una función dedicada print_pi_approximation().
  • Se incrementaron los puntos a 1,000,000 para una mejor precisión.
  • Se añadió un formato de salida más detallado.
  • Se incluyó el porcentaje de precisión de la aproximación.

Resumen

En este laboratorio, aprendimos primero a generar puntos aleatorios dentro de un cuadrado unitario utilizando el lenguaje de programación C, lo cual es una parte crucial del método de Monte Carlo para aproximar π. Sembramos el generador de números aleatorios con la hora actual y luego generamos 10,000 puntos aleatorios en el cuadrado unitario (0,0) a (1,1) utilizando la función rand().

A continuación, modificamos el programa para contar los puntos dentro de un cuarto de círculo y utilizamos esta información para aproximar el valor de π. Generamos 100,000 puntos aleatorios y comprobamos cuáles cayeron dentro del cuarto de círculo. Calculando la proporción de puntos dentro del círculo con respecto al número total de puntos, pudimos estimar el valor de π.