一、实验目的
1. 了解随机化算法的类型及特征;
2. 能够使用线性线性同余法生成系列随机数;
3. 能够通过随机实验的方法,估计数值的大小,理解估算值的精确度随算法的运行时间的增加而提高;
4. 针对具体问题,能够设计随机化算法;
5.能够为确定性算法引入随机成分,将其改造成随机化算法。
二、实验平台
1. Windows操作系统或Linux操作系统;
2. Python3.x;
3. PyCharm或Sublime或Jupyter Notebook。
三、实验内容
估算pi的值、估算定积分
四、算法设计
问题分析
(1)所选实验项目给定的已知
估算pi的值:已知圆的面积公式S=πr^2和正方形的面积公式S'=4r^2,利用随机采样的方法,通过计算落在圆内的点数与总点数之比,来近似计算π的值。
估算定积分:已知函数f(x)在区间[a,b]上的定积分公式∫f(x)dx,利用随机采样的方法,在该区间内随机取n个点,并计算其中位于函数曲线下方的点数,再通过计算该面积与整个区间面积之比,来近似计算定积分的值。
(2)求解目标
估算pi的值:通过随机采样的方法,近似计算π的值。
估算定积分:通过随机采样的方法,在给定区间内近似计算函数的定积分。
(3)条件
估算pi的值:二维平面上有一个正方形,其边长为2r,以及一个内切在正方形中心的圆形,半径为r。通过随机采样的方法,在正方形内部取n个点,并计算其中落在圆内的点数。
估算定积分:已知区间[a,b]和函数f(x)在该区间上的表达式。通过随机采样的方法,在该区间内取n个点,并计算其中位于函数曲线下方的点数。
问题建模
估算pi的值:
已知:二维平面上有一个半径为r的圆形和内切在该圆形中心的正方形。
求解目标:通过随机采样的方法,在正方形内部取n个点,并计算其中落在圆形内的点数,以此近似计算π的值。
相关条件:
(1)圆的面积公式:S = πr^2
(2)正方形的面积公式:S' = 4r^2
(3)随机采样的方式:在正方形内均匀地随机取n个点。
估算定积分:
已知:函数f(x)在区间[a,b]上的表达式。
求解目标:通过随机采样的方法,在该区间内取n个点,并计算其中位于函数曲线下方的点数,以此近似计算定积分的值。
相关条件:
(1)定积分的定义:∫f(x)dx
(2)随机采样的方式:在区间[a,b]内均匀地随机取n个点。
(3)点与函数之间的关系:若某点(x, y)满足y < f(x),则该点位于函数曲线下方。
算法描述
函数 estimate_pi(n):
初始化内圆点数 inside = 0
对于每个点 i in range(n):
生成随机坐标 (x, y) 在正方形 [-1, 1] x [-1, 1] 内部
如果 (x**2 + y**2 <= 1):
增加内圆点数 inside 的数量
计算圆周率 pi = 4 * inside / n
返回 pi
函数 trapezoid_rule(f, a, b, n):
计算步长 h = (b - a) / n
初始化积分值 s = 0.5 * (f(a) + f(b))
对于每个点 i in range(1, n):
计算当前点 x = a + i * h
将当前点的函数值 f(x) 加到积分值 s 上
计算积分面积 h * s
返回积分面积
函数 simpson_rule(f, a, b, n):
计算步长 h = (b - a) / n
初始化积分值 s = f(a) + f(b)
对于每个奇数点 i in range(1, n, 2):
计算当前点 x = a + i * h
将当前点的函数值 4 * f(x) 加到积分值 s 上
对于每个偶数点 i in range(2, n-1, 2):
计算当前点 x = a + i * h
将当前点的函数值 2 * f(x) 加到积分值 s 上
计算积分面积 h * s / 3
返回积分面积
函数 f(x):
返回 x**2
将估算圆周率的函数 estimate_pi(100000) 的返回值打印在屏幕上
将使用梯形法则计算函数积分的函数 trapezoid_rule(f, 0, 1, 10000) 的返回值打印在屏幕上
将使用辛普森法则计算函数积分的函数 simpson_rule(f, 0, 1, 10000) 的返回值打印在屏幕上
五、算法源码
估算pi值:
from random import random from math import sqrt DARTS=1000 hits=0.0 for i in range(1,DARTS+1): x,y=random(),random() dist=sqrt(x**2+y**2) if(dist<=1.0): hits=hits+1 pi=4*(hits/DARTS) print("PI值是{}".format(pi)) |
估算定积分:
import math import random upper_bound = 15 lower_bound = 10 def f_x_(x): outcome = 3 * (x ** 2) + 4 * math.cos(x) - 4 * x * math.sin(x) return outcome def F_x_(x): outcome = x ** 3 + 4 * x * math.cos(x) return outcome sum = 0 count = 1 while count <= 10000: sum = sum + f_x_(random.uniform(lower_bound, upper_bound)) count = count + 1 DefiniteIntegral_By_MonteCarloMethod = (upper_bound - lower_bound) * (sum / 10000) print("定积分:") print(DefiniteIntegral_By_MonteCarloMethod) |
六、测试数据
1、第一组数据
(1)输出
PI值是3.256
定积分:
2364.544812711267
2、第二组数据
(1)输出
PI值是3.196
定积分:
2361.7281846125984
3、第三组数据
(1)输出
PI值是3.112
定积分:
2361.450345444967
七、算法分析
结果分析:
估算圆周率:该算法使用Monte Carlo方法进行求解,随着n的增加,精度会逐渐提高。一般来说,如果采样点数足够大,比如n=100000,那么最终得到的圆周率值应该是比较接近真实值3.141592653589793的。
计算函数积分:该算法使用梯形法则和辛普森法则进行求解,随着n的增加,精度也会逐渐提高。然而,这些方法在处理非常复杂的函数时可能会出现误差。
时间复杂度分析:
估算圆周率:对于每个随机点,需要计算它是否位于内部圆中,因此时间复杂度为O(n)。
计算函数积分:梯形法则的时间复杂度为O(n),辛普森法则的时间复杂度为O(n),其中n是步数。
空间复杂度分析:
估算圆周率:只需要存储一些变量,因此空间复杂度很低。
计算函数积分:需要存储函数f(x)的值,并且在计算过程中需要存储一些变量,因此空间复杂度与函数f(x)和n有关。
八、实验总结
1.结论:
估算圆周率:该代码使用Monte Carlo方法估算圆周率的效果是比较好的,当n足够大时可以得到比较精确的结果。
计算函数积分:该代码使用了梯形法则和辛普森法则进行函数积分计算。这些方法在处理简单函数时准确性很高,但是对于复杂函数可能存在一定误差。
2.优化改进:
估算圆周率:在实践中,可以通过并行计算来加快Monte Carlo方法的运行速度。此外,也可以使用其他随机数生成器或者采用更高级别的统计学习方法来提高估算精度。
计算函数积分:对于某些情况下需要处理特别复杂的函数,可以考虑使用更高级别的数值积分方法来提高精度,并同时降低误差。此外,也可以使用自适应步长算法来调节步长大小以提高积分精度。