一、数学思维
# CalPi.py
n = 100
Pi = 0
for k in range(n):
Pi += 1 / pow(16, k) * (4 / (8 * k + 1) - 2 / (8 * k + 4) - 1 / (8 * k + 5) - 1 / (8 * k + 6))
print("圆周率值是:{}".format(Pi))
输出:
圆周率值是:3.141592653589793
二、工程思维:蒙特卡罗方法(Monte Carlo method)
圆周率:一个与正方形内切的圆的面积与该正方形的面积之商
πrr / 2r*2r = π/4
- 正方形的面积很好计算
- 圆的面积?
- 思考:对于一个区域面积,我们向它撒点或抛飞镖或扔石子,每一个撒点,它随机地可能会出现在这个区域中的任何一个位置上。如果我们给出的这个点的数量非常庞大,而且每一个点又尽可能地随机,那么在圆的内部的点就构成了圆的面积,在整个正方形中的所有撒点就是正方形的面积。通过圆内部点的数量与方形内部点的数量的比值就能够计算出圆周率
- 正方形内部有一个相切的圆,它们的面积之比是π/4。现在,在这个正方形内部,随机产生n个点,计算它们与中心点的距离,并且判断是否落在圆的内部。若这些点均匀分布,则圆周率 π/4 = count/n, 其中count表示落到圆内投点数 n:表示总的投点数。
# CalPiV1.py
import random
import time
DARTS = 1000 * 1000 # DARTS是总点数。同时通过下面循环的随机数确保点都在正方形内
hits = 0.0
start = time.perf_counter()
for i in range(1, DARTS + 1): # 使用循环生成随机数来模拟随机撒点
x, y = random.random(), random.random()
dis = pow(x * x + y * y, 0.5)
if dis <= 1.0:
hits += 1
Pi = 4 * (hits / DARTS)
print("圆周率值是:{}".format(Pi))
print("运行时间是:{:.5f}s".format(time.perf_counter() - start))
输出:
圆周率值是:3.140584
运行时间是:1.29082s
# CalPiV2.py
import random
def calpai():
n = 1000000 # 总点数
r = 1.0
x_neg, x_pos = - r, r
y_neg, y_pos = - r, r
count = 0 # 统计落到圆内的点数
for i in range(0, n):
x = random.uniform(x_neg, x_pos)
y = random.uniform(y_neg, y_pos)
if x*x + y*y <= 1.0:
count += 1
print((count / n) * 4)
calpai()
输出:
3.140096
-
数学思维的前提是需要有计算公式,如果没有计算公式,就无法使用
-
蒙特卡罗方法是计算思维,抽象的撒点过程,抽象为计算点的数量的过程,并且用计算机通过循环自动化运行,抽象+自动化
-
如果一个问题有数学公式,用公式求解更精确,但很多问题没有数学规则,比如四色定理并不能通过数学公式来解决,也是用计算机来解决的
-
对一个程序,运行的大部分时间只消耗在20%的代码上,比如在循环上
三、蒙特卡洛方法的基本思想 -
通常蒙特卡罗方法可以粗略地分成两类:**一类是所求解的问题本身具有内在的随机性,借助计算机的运算能力可以直接模拟这种随机的过程。**例如在核物理研究中,分析中子在反应堆中的传输过程。中子与原子核作用受到量子力学规律的制约,人们只能知道它们相互作用发生的概率,却无法准确获得中子与原子核作用时的位置以及裂变产生的新中子的行进速率和方向。科学家依据其概率进行随机抽样得到裂变位置、速度和方向,这样模拟大量中子的行为后,经过统计就能获得中子传输的范围,作为反应堆设计的依据。
-
另一种类型是所求解问题可以转化为某种随机分布的特征数,比如随机事件出现的概率,或者随机变量的期望值。通过随机抽样的方法,以随机事件出现的频率估计其概率,或者以抽样的数字特征估算随机变量的数字特征,并将其作为问题的解。这种方法多用于求解复杂的多维积分问题。
PS. source, python123.io