【基础概念】蒙特卡洛算法

概念

蒙特卡洛算法是一种基于随机抽样的计算方法。

它的核心思想是通过大量随机实验来估计问题的解。这种方法适用于那些难以用解析方法求解的问题。

示例

下面以计算圆周率 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 为例,说明蒙特卡洛算法的具体应用。

由于 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 是一个确定的值,我们需要对其设计随机试验,来求其估值。

假设我们有一个边长为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 1 </math>1 的正方形,这个正方形内接一个半径为0.5的圆。我们在正方形内随机撒点,当随机点在正方形内均匀分布时,落在圆内的概率等于圆的面积与正方形面积之比。即圆的面积是 <math xmlns="http://www.w3.org/1998/Math/MathML"> π ∗ 0. 5 2 π*0.5^2 </math>π∗0.52,正方形面积是 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 1 </math>1,所以落在圆内点的数量与撒点的总数之比就是 <math xmlns="http://www.w3.org/1998/Math/MathML"> π 4 \frac{π}{4} </math>4π。

下面给出 Python 代码实现和详细注释。

python 复制代码
# 导入随机数模块和绘图模块
import random
import matplotlib.pyplot as plt

# 定义Point类表示二维点
class Point:
    def __init__(self,x=None,y=None):
        # 如果x,y未提供则生成随机坐标(0-1之间)
        self.x=x if x is not None else random.random()
        self.y=y if y is not None else random.random()
    
    def __str__(self):
        # 返回点的字符串表示
        return str(self.x)+','+str(self.y)
    
    def dis2(self,a):
        # 计算当前点到点a的平方距离(避免开方运算提高效率)
        return (self.x-a.x)**2+(self.y-a.y)**2


# 蒙特卡洛计算π的函数
def calculator(N):
    # 创建图形和坐标系
    fig, ax = plt.subplots()
    cnt=0  # 统计落在圆内的点数

    # 创建圆心点(0.5,0.5)
    o=Point(0.5,0.5)
    # 用黄色标记圆心
    plt.plot(o.x,o.y,'o','yellow')
    # 绘制半径为0.5的黑边圆形
    circle=plt.Circle((o.x,o.y),0.5,fill=False,color='black',linewidth=1)
    ax.add_patch(circle)

    # 进行N次蒙特卡洛实验
    for i in range(N):
        a=Point()  # 生成随机点
        if a.dis2(o) <= 0.5*0.5:  # 判断点是否在圆内(比较平方距离)
            cnt+=1  # 圆内点数+1
            plt.plot(a.x,a.y,'o',color='blue')  # 圆内点用蓝色标记
        else:
            plt.plot(a.x,a.y,'o',color='red')  # 圆外点用红色标记

    # 设置坐标轴范围和比例
    ax.set_xlim(0, 1)
    ax.set_xlim(0, 1)
    ax.set_aspect('equal')  # 保证x,y轴比例相同
    
    # 计算π的估计值
    S=cnt/N  # 圆内点比例,由于正方形面积为1,故S也是圆的面积的估值
    pi=S*4  # S=πr²,这里r=0.5
    print(N,pi)  # 输出点数和π估计值
    plt.show()  # 显示图形

# 主程序入口
if __name__=="__main__":
    # 获取用户输入的实验次数
    T=int(input())
    # 调用计算函数
    calculator(T)

随着采样点数量的增加,估计结果会越来越接近真实的π值。

上图展示了不同的采点数量估计出的 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 值。第一列为采点数量,第二列为 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 值。

使用10000个随机点时,估计值通常会精确到小数点后一两位。当采样点达到百万级别时,精度可以提高到小数点后三位或四位。这种方法的精度取决于随机数的质量,以及采样点的数量。

由于蒙特卡洛算法具有随机性,随着采点数量的增加,具体到每次实验中,我们估计的结果与真实值之差并不一定会单调减小。但是根据大数定律,估算结果的期望值会趋近于真实值。

总结

通过计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 的例子可以看出,蒙特卡洛算法的关键在于设计合适的随机实验。需要确保随机采样能够准确反映待求解问题的特征。

蒙特卡洛算法的优势在于实现简单,不需要复杂的数学推导。它的计算过程可以很容易地并行化,因为每个随机点的计算都是独立的。

不过,这种方法也存在缺点,主要是收敛速度较慢。要提高一位小数的精度,通常需要增加100倍的采样点。

蒙特卡洛算法虽然简单,但在许多实际问题中都能发挥重要作用。除了计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 值,它还可以用于期权定价、粒子输运模拟、图像渲染等场景。这些应用都利用了随机采样能够近似复杂系统行为的特性。

相关推荐
majingming123几秒前
GRBL_UNO R3编译下载
单片机·算法
森焱森10 分钟前
驱动开发,队列,环形缓冲区:以GD32 CAN 消息处理为例
c语言·单片机·算法·架构
GeminiJM41 分钟前
分布式选举算法<一> Bully算法
分布式·算法
爱吃芝麻汤圆1 小时前
分布式——分布式一致性算法(共识算法)
分布式·算法·共识算法
周方.1 小时前
191. 位1的个数
数据结构·算法·leetcode·链表·职场和发展
可可格子衫1 小时前
129. 求根节点到叶节点数字之和 --- DFS +回溯(js)
javascript·算法·深度优先
Tony沈哲2 小时前
基于 MODNet 和 Face Parsing 实现高质量人像分割与换发色
深度学习·opencv·算法
缘友一世2 小时前
设计模式之五大设计原则(SOLID原则)浅谈
java·算法·设计模式
圣保罗的大教堂3 小时前
leetcode 1432. 改变一个整数能得到的最大差值 中等
算法·leetcode·职场和发展
Coding小公仔3 小时前
LeetCode 48. 旋转图像
算法·leetcode·职场和发展