蒙特卡罗思维计算圆周率的三种算法

蒙特卡罗思想计算圆周率的三种算法

本篇文章介绍计算圆周率的几种算法,都是应用蒙特卡罗思想:或称计算机随机模拟方法,是一种基于“随机数”的计算方法。

方法一:蒙特卡罗方法,内切圆

1.1思想

         有一个以(0,0)为中心的2*2的正方形,及这个正方形的半径为1的内接圆,取这个正方形范围内的一点,则这个点落入内接圆的概率为PI/4。

1.2程序

程序分为两部分:(1)随机生成正方形内的一点(2)计算落入内接圆的概率,从而求得PI。

import java.util.Random;

public class MonteCarlo  {
	int m = 0;//落入内接圆的次数
	int n = 10000000;//试验进行次数
	float x;//点的x坐标值
	float y;//点的y坐标值
	double result = 0;//结果,即为PI
	Random r = new Random();//Random对象,用于生成随机数
	public static void main(String[] args){
		MonteCarlo c = new MonteCarlo();
		c.calculatePI();
	}
	public float getNum(){
		float tmp = 1-r.nextFloat()*2;//nextFloat生成[0,1]的浮点数
		return tmp;
	}
	public void calculatePI(){
		for(int i = 0; i<n;i++){//进行n次试验
			x=getNum();
			y=getNum();
			float tmp = (float) java.lang.Math.sqrt(x*x+y*y);//开根号
			if(tmp<=1)
				m++;//落入内接圆的次数
		}
		result = (4*(float)m)/n;//PI
		System.out.println("m: "+m);
		System.out.println("n: "+n);
		System.out.println("pi: "+result);
	}
}

方法二:蒲丰投针方法

2.1思想

         在平面上画一组间距为d的平行线,将一根长度为l(l<d)的阵任意掷在这个平面上,此阵与平行线中任一条相交的概率是:p = 2l/(PI*d)

2.2程序

程序分为如下几个步骤:(1)随机得到一个点和一个角度(2)计算另一个点位置(都只考虑垂直位置)(3)计算这两个点分别跨越了几条平行线

import java.util.Random;

public class PuFeng {

	int n = 10000000;//试验进行次数
	int m = 0;//相交次数
	double l = 2;//针的长度
	double d = 5;//平行线间距
	double pi = 0;//结果
	int lNum = 10000;//线的条数
	Random r = new Random();//用于生成随机数
	public static void main(String[] args){
		PuFeng p = new PuFeng();
		p.calculatePI();
	}
	public void calculatePI(){
		for(int i = 0; i <n;i++){
			double point = getPoint(); 
			double angle = getAngle();
			double anotherPoint = point+l*java.lang.Math.sin(angle);//得到第二个点垂直位置
			int crossNum1 = (int) (point/d);//第一个点前面有几条平行线
			int crossNum2 = (int) (anotherPoint/d);//第二个点前面有几条平行线
			if((crossNum1-crossNum2)!=0)//若差等于0,则与平行线不相交
				m++;
		}
		pi= (2*n*l)/(m*d);
		System.out.println("m: "+m);
		System.out.println("n: "+n);
		System.out.println("result: "+pi);
	}
	//随机得到平行线范围内的一点
	public double getPoint(){
		double tmp = r.nextDouble()*lNum*l;
		return tmp;
	}
	//随机得到0~360角度
	public double getAngle(){
		double tmpAngle = (double) (r.nextDouble()*Math.PI);;
		return tmpAngle;
	}
}

方法三:互质方法

3.1思想

         随机取两个自然数,则这两个数互质的概率为:6/(PI*PI)

3.2程序

         该程序分为几个步骤:(1)生成两个自然数(2)判断是否互质(3)计算互质的概率

import java.util.Random;

public class PrimeNum {
	Random r = new Random();//用于生成随机数
	int m = 0;//互质的次数
	int n = 1000000;//实验次数
	float result = 0;//结果,即PI
	public static void main(String[] args){
		PrimeNum p = new PrimeNum();
		p.calculatePI();
	}
	public int getNum(){
		int tmp = r.nextInt();
		while(tmp<1){//r.nextInt()得到了的可能是负数
			tmp = r.nextInt();
		}
		return tmp;
	}
	public Boolean checkPrime(int a, int b){//判断两个数是否互质
		if(a<b){
			int tmp = a;
			a = b;
			b = tmp;
		}
		int c = 0;
		while((c = a%b)!= 0){
			a = b;
			b = c;
		}
		if(b == 1)
			return true;
		else
			return false;
	}
	
	public void calculatePI(){
		for(int i = 0; i <n;i++){//进行n次实验
			int num1=getNum();//随机获得两个自然数
			int num2 = getNum();
			if(checkPrime(num1,num2))//判断是否互质
				m++;//若互质,则m+1
		}
		result = (float) java.lang.Math.sqrt((6*n)/(float)m);
		System.out.println("m: "+ m);
		System.out.println("n: "+ n);
		System.out.println("result: "+result);
	}
}


1楼godfrey902012-12-14 18:25
总结的很好!
Re: shanxing26天前 20:53
回复godfrey90n3q,我会继续努力的!