摘要:当程序员遇上π,蒙特卡洛算法成了他们的魔法棒。本文用一段C语言代码,将随机点的雨滴洒向数字的海洋,用概率的网捕捉π的踪迹。这不仅是一场算法的探险,更是对编程魔法的一次奇妙展示。


认识蒙特卡洛算法

蒙特卡洛算法是一类基于概率的算法的统称,不是特指某一种算法。

它也被称为统计模拟方法,是指使用随机数来解决很多计算问题的方法。

它的工作原理为两件事:

  • 不断抽样
  • 逐渐逼近

使用蒙特卡洛算法

今天我们来用它来逼近 π 。

  • 首先,我们知道:圆的面积计算公式为 代码中的大数定律:蒙特卡洛算法逼近圆周率π_#include
  • 接着,我们设想,有一个半径为1的圆,它的面积为 π
  • 然后我们用一个边长为 1 的正方形把它切开,让这个圆只保留1/4,此时它的面积则为 代码中的大数定律:蒙特卡洛算法逼近圆周率π_#include_02
  • 然后我们在这个正方形里面随机的打点

代码中的大数定律:蒙特卡洛算法逼近圆周率π_#include_03

设我们共随机打了 D 个点,有 C 个点在 1/4圆中,那么C/D就会逼近(π / 4)/ 正方形的面积, 而因为我们正方形的面积是1,所以它也就是会逼近π / 4这个值。

C / D 不断逼近 π / 4, 也就是说,4 * C / D在不断地逼近π

我们已经知道原理了,现在用代码去逼近它来爽一下。

程序设计思路

这个程序比较简单,我们只要生成随机数,然后用随机数 / 随机数最大值把随机数限制在0~1之间就可以了。

唯一的难点是:怎么判断这个随机点在不在四分之一圆上?

我们可以用勾股定理来轻松解决这个问题:

我们想象中的圆的半径是1,而这个正方形的坐标圆点,它其实就是圆心。所以,我们只要算出坐标距离圆点的直线距离,是否大于等于1,就可以判断出这个点是否在四分之一圆内。

勾股定理代码中的大数定律:蒙特卡洛算法逼近圆周率π_#define_04

代码实现

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

#define MAX 1000000000

int main()
{
	long long i = LONG_MAX;
	double x = 0.0;
	double y = 0.0;
	double pi = 0.0;//圆周率
	long long count = 0;

	//设置随机种子
	srand((unsigned)time(NULL));

	for (i = 0; i < MAX; i++)
	{
    //设置随机坐标
		x = (double)rand() / RAND_MAX;
		y = (double)rand() / RAND_MAX;
		printf("%lf %lf\n", x, y);

		//判断是否在1/4圆内
		if (sqrt(pow(x, 2) + pow(y, 2)) <= 1)
		{
			//记录随机数在1/4圆内的数量
			count++;
		}
	}

	//利用 PI = 4C/D 来求出 PI 的近似值
	pi = (4.0 * count) / MAX;

	printf("%lf\n", pi);

	return 0;
}

运行结果

代码中的大数定律:蒙特卡洛算法逼近圆周率π_#include_05

结论

蒙特卡洛算法通过随机抽样,来逼近复杂问题的解。本文展示了其在计算圆周率 π 的应用。通过在单位正方形内随机生成点,并利用勾股定理判断点是否落在内嵌的四分之一圆内,我们得到了 π 的近似值。这种方法简单有效,随着抽样数量的增加,结果的精度也会提高。