本文刊载在2020年7月20日第28期《电脑报》32版。欢迎前往中国邮政微商城或杂志铺订阅《电脑报》,邮发代号77-19。
之前电脑报刊登了一篇用VB计算圆周率π值的文章。使用了π/4=1-1/3 1/5 … 1/i,计算π的近似值,i值越大精度越高。这种算法不够直观,其实不太容易理解。我另外选了两种计算π的算法:蒙特卡罗方法和直接测量法,并用Scratch编程来计算圆周率,这样小朋友都能很容易理解圆周率的定义和计算了。
一、蒙特卡罗方法
蒙特卡洛方法(Monte Carlo,简称MC)是冯·诺依曼等人提出的统计模拟方法,蒙特卡洛这个名字来源于赌场,表示这种算法的不确定性原理与赌博类似。
假设有一个边长为1的正方形区域,有一个圆和这个正方形内切。我们知道正方形面积是边长a的平方,圆形面积是π乘以半径R的平方。由于是内切圆所以正方形边长等于2R,圆形和正方形面积的比值k等于π/4。
如果能够知道k的值,就能得到π=4k,这就是估计圆周率的核心思想。
随机投点,落在圆内的比例除以4就是π
现在我们向矩形范围内随机画点,任何位置被选中的概率都是相等的,图中共投了1000个点,经过统计落在圆内的点为787个,由于投点是随机的,所以可以近似认为圆形和矩形的面积比k等于点数比,即k=787/1000=0.785,所以圆周率π=4k=4x0.787=3.148,至此圆周率π的估算已经完成。
新建角色“圆心”和“笔”,“圆心”就在(0,0)画一个点,“笔”隐藏显示。
在程序中我们设置了3个变量,“pi”存储π值、“总投放点数”设置总数、“落在范围内的点”记录在圆内的点。
调用画笔扩展,重复执行“总投放点数”次。在XY坐标-90到90之间的方形区域随机画点。
判断如果随机画的这个点到角色“圆心”的距离大于90不成立。即表示这个点在圆的范围内(含圆的边)。将“落在范围内的点”加1。
循环完毕,用“落在范围内的点”除以“总投放点数”就获得面积比k,乘以4就得到π值了。运行时请打开加速模式,不然会运算到天荒地老。
蒙特卡洛方法是一种依赖于重复性随机采样,进而获得数值解的建模方法。对于复杂曲线积分这种很难通过理论求解的情况,可以通过蒙特卡洛方法获得一个近似解。我们用Scratch编程后多次运行就可发现,算出的π值偏差比较大,而提高“总投放点数”并不能很好的提升计算精度,这应该是由于计算机产生的随机数是伪随机数造成的。
二、程序测量法
我们知道π的定义是圆的周长与直径的比值。
我们用Scratch画出半个边数超多(100000条边)的多边形。这个多边形由于每条边都很短,可以认为近似是一个圆,这个半圆的终点到起点间的距离就是圆的直径。边长乘以边数就是这个圆的周长。两者相除就可以算出π的值了。
新建角色“起点”,在造型中背景放到最大后在中心点一个小点。移动到(0,-160)作为起点位置。
对小猫编程。
设置“pi”记录计算结果,通过控制“边长”(0.01)、“边数”(100000)的大小控制近似圆形的大小,提高计算π值的精度,边数越多π的精度应该越高。
移动到(0,-160)的起点位置,面向90度方向,重复执行边数除以2次,因为我们只需要画一个半圆用来测量直径。画正多边形的方法电脑报以前已经介绍过就是移动“边长”步,左转360除以“边数”度。这样画出的半圆形终点到角色“起点”之间的距离就是圆的直径。
边长乘以边数就是圆的近似周长。
将“pi”设为“边长”*“边数”/到“起点”的距离。
要想看到最精确的计算结果,有一个小技巧,要点击单独放在代码区的变量“pi”才行。计算结果为3.141592653072866与我们已知的π值相当接近,说明这个方法计算结果相当精确。
这个方法的思维方法最为直接,就是测量出圆的周长和直径直接相除就可以得到π值。但是对于古人来说周长和直径都很难精确测量,所以才有那么多数学家想方设法去提高π的计算精度,但是对于程序来说这个直接的方法却意外的容易和精确。
我们程序中设定的边长和边数数值只是个经验数值,只是因为画出来的半圆大小比较合适。其实只要多边形边数超过100条边时π值的精度就已经达到3.141了,比蒙特卡洛方法效果好得多,而且随着边数的提高计算精度稳步提升,而且边长对于π计算结果影响不大,只是影响视觉效果而已。
,