用蒲丰(buffon)投针来估计 π \pi π
1 问题描述
2 问题求解
3 Python实现
3.1 循环形式
3.2 向量形式
1 问题描述
buffon投针问题是18世纪首先被Georges-Louis Leclerc, Comte de Buffon提出的。假设我们有一个由平行的木条组成的地板,每条木条的宽度都是 a a a,我们把一个长度为 l ( l < a ) l(l<a) l(l<a)的针随意扔到地板上,针与木条相交的概率是多少?
2 问题求解
设 x x x是针的中心到最近木条的距离, θ \theta θ是针与该木条之间的角度,如下图 ( a ) (a) (a)。因此当 x ≤ l 2 s i n ( θ ) x≤\frac{l}{2}sin(\theta) x≤2lsin(θ)时,针与木条相交。
临界条件为
x
≤
l
2
s
i
n
(
θ
)
x≤\frac{l}{2}sin(\theta)
x≤2lsin(θ),而
x
x
x的范围为
0
≤
x
≤
a
2
0≤x≤\frac{a}{2}
0≤x≤2a,
θ
\theta
θ的范围为
0
≤
θ
≤
π
0≤\theta≤\pi
0≤θ≤π,因此我们可以得到图
(
b
)
(b)
(b)。根据几何概率,针与木条相交的概率就为图中阴影部分的面积与整个矩形的面积的比值。因此有
P
=
∫
0
π
l
2
sin
(
θ
)
d
θ
a
2
∗
π
=
2
l
a
π
P=\frac{\int_{0}^{\pi} \frac{l}{2}\sin(\theta)d\theta}{\frac{a}{2}*\pi}=\frac{2l}{a\pi}
P=2a∗π∫0π2lsin(θ)dθ=aπ2l,据此,我们可以得到
π
\pi
π的估计为
π
^
=
2
l
a
P
\hat{\pi}=\frac{2l}{aP}
π^=aP2l。
3 Python实现
总体思路:生成 n n n个(即代表进行 n n n次实验)服从 U ( 0 , π ) U(0, \pi) U(0,π)的随机数 θ \theta θ和 n n n个服从 U ( 0 , a 2 ) U(0, \frac{a}{2}) U(0,2a)的随机数 x x x,令 k k k为实验成功的次数,初始为 0 0 0,即对于每对随机数 ( θ , x ) (\theta, x) (θ,x),如果 x ≤ l ∗ sin θ 2 x≤\frac{l*\sin\theta}{2} x≤2l∗sinθ,那么就视为实验成功, k k k加 1 1 1。因此最后针与木条相交的概率 P = k n P=\frac{k}{n} P=nk,从而可得 π \pi π的估计为 π ^ = 2 l n a k \hat{\pi}=\frac{2ln}{ak} π^=ak2ln。(产生随机数的方法)
3.1 循环形式:
import numpy as np
#定义一个估计π的函数,其中n为实验次数
def buffon(n, l=0.8, a=1):
k = 0
#产生n个服从U(0,π)的随机数θ
theta = np.random.uniform(0, np.pi, n)
#产生n个服从U(0,a/2)的随机数x
x = np.random.uniform(0, a / 2, n)
#进行循环判断
for i in range(n):
if x[i] <= l * np.sin(theta[i]) / 2:
k = k + 1
pi = 2 * l * n / (a * k)
return pi
结果:
#进行10**8次实验
print(buffon(10 ** 8))
输出:3.1411176760252406
3.2 向量形式:
#定义一个估计π的函数,其中n为实验次数
def buffon2(n, l=0.8, a=1):
#产生n个服从U(0,π)的随机数θ
theta = np.random.uniform(0, np.pi, n)
#产生n个服从U(0,a/2)的随机数x
x = np.random.uniform(0, a / 2, n)
#不进行循环,直接利用numpy的性质,计算速度会更快
k = np.sum(x <= l * np.sin(theta) / 2)
pi = 2 * l * n / (a * k)
return pi
结果:
#进行10**8次实验
print(buffon2(10 ** 8))
输出:3.1414584813950164