这是昨日我在CSDN上碰到的一个问题所引发的思考和所得。
有一个人在CSDN BBS上提问一段程序:
1 #include <stdlib.h> 2 #include <stdio.h> 3 #define LOOP 1000 4 void main() 5 { 6 int rgnC=0; 7 for(int i=0;i<LOOP;i++) 8 { 9 int x=rand();10 int y=rand();11 if(x*x+y*y<RAND_MAX*RAND_MAX)12 rgnC++;13 }14 printf("%d\n",rgnC);15 }
他的问题是:这段程序是不是和1/4圆和正方形的大小有关,为什么LOOP越大,rgnC越大,是不是程序错了。
其实LOOP越大,rgnC必然越大,但是rgnC/LOOP确是收敛的。
开始我的回答就是这些,没有去想这段程序的作用和这个收敛值到底是干嘛的。直到后来又有一个人给出了这个程序是用来估算圆周率的,我才发现我的思考是多么的不深刻和不完善。
其实随着LOOP的增大,rgnC/LOOP确实会收敛于一个值π/4。这是用概率来估算圆周率的一个方法。
圆的面积公式:C = π × r^2 公式1
正方形面积公式:S = k^2 公式2
这里用1/4圆,它的半径r和正方形的边长k相等。
因为要计算π,所以圆的面积是无法用公式1计算出来的。所以可以考虑用概率的方法。
我们可以构建如上的模型,我们可以随意在正方区域内撒点(就像撒米在地上一样),然后我们知道撒入1/4圆(黑色)区域内的概率是P = (C/4)/S = π/4,也就是说得到P,就可以得到π。
可以用程序很轻松的得到解决。
改造后的程序代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 int i = 0,j = 0; 7 int test = 0,x,y; 8 for(i = 100;i<1000000000;i*=10){ 9 test = 0;10 for(j = 0;j<i;j++){11 x = rand();12 y = rand();13 if((x*x + y*y) < RAND_MAX*RAND_MAX){14 test++; 15 }16 } 17 printf("scale = %d,π= %f\n",i,(double)test*4/i);18 }19 return 0;20 }
程序很好理解:RAND_MAX为正方形边长,x,y为随机的数,X*X+Y*Y = R^2,即随机生成的圆的面积/π ,若这个数小于 RAND_MAX*RAND_MAX,即为黑色区域(1/4圆)面积/π,则test自增1。
说的通俗一点就是在正方形区域内随意撒点,若在黑色区域内则test++,最后test和测试范围 i 相除可以近似得到概率P,则可近似得到圆周率π = P*4
程序运行结果如下:
scale = 100,π= 3.200000
scale = 1000,π= 3.076000
scale = 10000,π= 3.113200
scale = 100000,π= 3.139800
scale = 1000000,π= 3.139908
scale = 10000000,π= 3.140975
scale = 100000000,π= 3.141385
来源:https://www.cnblogs.com/tim13/archive/2011/09/04/2165929.html