蒙特卡罗用于布丰投针实验
%% (1)预备知识
% rand(m,n)函数产生由在[0,1]之间均匀分布的随机数组成的m行n列的矩阵(或称为数组)。
rand(5,4)
% 0.8300 0.1048 0.2396 0.4398
% 0.5663 0.1196 0.8559 0.5817
% 0.9281 0.2574 0.3013 0.9355
% 0.3910 0.3173 0.2108 0.1676
% 0.3645 0.4372 0.8819 0.9232
rand(3) % 若只给一个输入,则会生成一个方阵
% 0.1709 0.4951 0.0541
% 0.9374 0.8500 0.6155
% 0.2400 0.3156 0.5741
% a + rand(m,n)*(b-a) 可以输出在[a,b]之间均匀分布的随机数组成的m行n列的矩阵。
-2 + rand(3,2) * (2 - (-2)) % 输出在[-2,2]之间均匀分布的随机数组成的3行2列的矩阵。
% -1.2743 0.6013
% -1.3084 0.0766
% 1.5075 0.7563
% a + rand(m,n)*(b-a)等价于unifrnd(a,b,m,n)
unifrnd(-2,2,3,2)
%% (2)代码部分
l = 0.520; % 针的长度(任意给的)
a = 1.314; % 平行线的宽度(大于针的长度l即可)
n = 1000000; % 做n次投针试验,n越大求出来的pi越准确
m = 0; % 记录针与平行线相交的次数
x = rand(1, n) * a / 2 ; % 在[0, a/2]内服从均匀分布随机产生n个数, x中每一个元素表示针的中点和最近的一条平行线的距离
phi = rand(1, n) * pi; % 在[0, pi]内服从均匀分布随机产生n个数,phi中的每一个元素表示针和最近的一条平行线的夹角
% axis([0,pi, 0,a/2]); box on; % 画一个坐标轴的框架,x轴位于0-pi,y轴位于0-a/2, 并打开图形的边框
for i=1:n % 开始循环,依次看每根针是否和直线相交
if x(i) <= l / 2 * sin(phi (i)) % 如果针和平行线相交
m = m + 1; % 那么m就要加1
% plot(phi(i), x(i), 'r.') % 模仿书上的那个图,横坐标为phi,纵坐标为x , 用红色的小点进行标记
% hold on % 在原来的图形上继续绘制
end
end
p = m / n; % 针和平行线相交出现的频率
mypi = (2 * l) / (a * p); % 我们根据公式计算得到的pi
disp(['蒙特卡罗方法得到pi为:', num2str(mypi)])
%% (3) 由于一次模拟的结果具有偶然性,因此我们可以重复100次后再来求一个平均的pi
result = zeros(100,1); % 初始化保存100次结果的矩阵
l = 0.520; a = 1.314;
n = 1000000;
for num = 1:100
m = 0;
x = rand(1, n) * a / 2 ;
phi = rand(1, n) * pi;
for i=1:n
if x(i) <= l / 2 * sin(phi (i))
m = m + 1;
end
end
p = m / n;
mypi = (2 * l) / (a * p);
result(num) = mypi; % 把求出来的myphi保存到结果矩阵中
end
mymeanpi = mean(result); % 计算result矩阵中保存的100次结果的均值
disp(['蒙特卡罗方法得到pi为:', num2str(mymeanpi)])