转自: http://www.cnblogs.com/tim13/archive/2011/09/04/2165929.html
这是昨日我在CSDN上碰到的一个问题所引发的思考和所得。
有一个人在CSDN BBS上提问一段程序:
#include <stdlib.h>
#include <stdio.h>
#define LOOP 1000
void main()
{
int rgnC=0;
for(int i=0;i<LOOP;i++)
{
int x=rand();
int y=rand();
if(x*x+y*y<RAND_MAX*RAND_MAX)
rgnC++;
}
printf("%d\n",rgnC);
}
他的问题是:这段程序是不是和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,就可以得到π。
可以用程序很轻松的得到解决。
改造后的程序代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0,j = 0;
int test = 0,x,y;
for(i = 100;i<1000000000;i*=10){
test = 0;
for(j = 0;j<i;j++){
x = rand();
y = rand();
if((x*x + y*y) < RAND_MAX*RAND_MAX){
test++;
}
}
printf("scale = %d,ヲミ= %f\n",i,(double)test*4/i);
}
return 0;
}
程序很好理解: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