最近看了点数学资料,也动手写了一下最简单的算法,记录下来:
1、蒙特卡洛计算PI值
-
原理说明
我们先花一个圆,然后画出圆的外切正方形,圆的半径记为R,则矩形面积为,圆形面积为
,我们在矩形面积内随机撒点,当撒点足够多时,点的数量就代表了图形的面积,我们也就知道了圆形面积除以矩形面积的值,也就可以算出
的近似值了。
-
程序代码
import random
#随机点的x、y值
x = 0
y = 0
#圆内点计数及总随机点数
circle_cnt = 0
point_set_num = 100000000
#在总点数次数内重复取数,并判断是否落在圆内,同时计数
for i in range(point_set_num):
x = random.uniform(-1,1)
y = random.uniform(-1,1)
if (x**2 + y**2)**0.5 <= 1:
circle_cnt += 1
#隔一定时间打印一次数量,提示程序在运行中
if i % 10000000 == 0:
print("===>{}".format(i))
#最后输出PI的近似值
print("PI's value is: {}.".format(circle_cnt/point_set_num*4))
-
输出结果
===>0
===>10000000
===>20000000
===>30000000
===>40000000
===>50000000
===>60000000
===>70000000
===>80000000
===>90000000
PI's value is: 3.14171748.
2、割圆法计算PI值
-
原理说明
先花一个圆内的内接正六边形,并求出面积,这时面积和圆实际面积相差很大;
进一步扩充内接图形的边,扩展为12个边,24、48、96....,内接图形的面积将逐步趋近于圆形;
-
程序代码
import math
#将内接图形扩展20次,得到3145728边的正内接图形,并计算图形面积
for i in range(20):
split_num = 6*2**i
print(split_num, end=" ==> ")
#正六边形时,面积计算 R*R*sin30*cos30*6=pi*R*R,pi=sin30*cos30*6
#以此类推到更多边来贴近pi的实际值,公式如下:
print(math.sin(math.radians(360/split_num/2))*math.cos(math.radians(360/split_num/2))*split_num)
-
输出结果
6 ==> 2.598076211353316
12 ==> 2.9999999999999996
24 ==> 3.105828541230249
48 ==> 3.1326286132812378
96 ==> 3.1393502030468667
192 ==> 3.1410319508905093
384 ==> 3.1414524722854615
768 ==> 3.1415576079118575
1536 ==> 3.1415838921483177
3072 ==> 3.1415904632280505
6144 ==> 3.141592105999271
12288 ==> 3.1415925166921568
24576 ==> 3.1415926193653836
49152 ==> 3.1415926450336906
98304 ==> 3.1415926514507673
196608 ==> 3.141592653055037
393216 ==> 3.141592653456103
786432 ==> 3.141592653556371
1572864 ==> 3.1415926535814376
3145728 ==> 3.141592653587704
后面这种计算方法还是比较贴近的。