简介
在本实验中,我们将探索如何使用蒙特卡洛模拟(Monte Carlo simulation)在 C 编程中估计概率。我们将从定义一个简单的随机实验开始,比如抛硬币,然后运行多次试验来统计成功结果的数量。最后,我们将通过成功次数除以试验总次数来计算估计概率。本实验通过 C 语言对概率和组合数学的基本概念进行了实际介绍,这些都是数据分析和决策的必备技能。
在本实验中,我们将探索如何使用蒙特卡洛模拟(Monte Carlo simulation)在 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
srand(time(NULL)) 为随机数生成器设定种子rand() % 2 以相等的概率生成 0 或 1## 创建源文件
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++) {
// 生成 0 到 1 之间的随机 x 和 y 坐标
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
(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
srand(time(NULL)) 确保不同的随机序列在本实验中,我们学习了如何在 C 语言中使用蒙特卡洛模拟来定义一个随机实验。我们创建了一个简单的抛硬币模拟来演示关键概念。首先,我们为随机数生成器设定种子并模拟抛硬币,统计成功结果(正面朝上)的数量。然后,我们通过将成功结果的数量除以试验的总次数来估计正面朝上的概率。输出结果显示,对于公平的抛硬币,估计概率接近预期值 0.5。