蒙特卡洛估算派的值Java,各種求圓周率π的算法(蒙特卡洛法的Java實現)

什么是算法?簡單地說,算法就是有窮規則構成的用於解決某一類問題的運算序列或執行步驟。在《算法之美:隱匿在數據結構背后的原理》第1章中我們講到要解決一個問題可能會有不同的方法,當時所舉的例子就是求圓周率π的近似值。對於這個問題你能想到多少種算法呢?

701a2d3f6811675d7141517c37ec0333.png

探秘

匯集經典問題,暢享編程技法之趣;

點撥求職熱點,敲開業界名企之門。

方法(1):首先根據微積分中的泰勒公式,可以使用下面這個公式來求π的近似值

103bdf52a337c8cfd0578faccad9d5a5.png

方法(2):其次可以還可以利用下面這個馬青公式來求解π的近似值:

88c7d0ae7729d9062b2965e6ccf64283.png

馬青公式由英國天文學家約翰·馬青(John Machin,1686 –1751)於1706年發現,他利用這個公式計算到了100位的圓周率。此外,上式中的反三角函數可以領用下面這個泰來展開式進行計算:

ba37d3d097e03ecbc1633405e0b73d9b.png

方法(3):最后,也是我們准備來動手實踐一下的就是利用蒙特卡洛法。這個方法背后的理論基礎是概率論中的伯努利大數定律。眾所周知,圓的面積公式為 S= πr2,當 r = 1 時,S = π。如果在一個邊長為1的正方形中有一個內切圓,那么該圓的面積就是π/4。利用這一原理,可以假設有大量的隨機點等概率均勻地落入此正方形中。若正方形的面積為S',內切圓的面積為S,如果落入正方形中的點數為N',落入內切圓的面積為N,這時便有 S'/S = N'/N,所以可據此求得π = 4×N/N'。

下面就編寫一個Java程序來實現蒙特卡洛法求π的近似值:

import java.io.BufferedReader;import java.io.InputStreamReader;

public class MonteCarloPi {

public static void main(String[] args) throws Exception{

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.print("How many darts shoud I toss at the board?\n");

String s = br.readLine();

int numberOfDarts = Integer.parseInt(s.trim());

double radius = 1.0;

Dartboard d = new Dartboard(radius);

for(int i=1; i<=numberOfDarts; i++){

Toss t = Toss.getRandom(radius);

d.strike(t);

}

double fractionIn = d.getFractionIn();

double pi = 4.0 * fractionIn;

System.out.println("Pi is approximately "+pi);

}

}

class Dartboard{

private double radius;

private int insideCircle, outsideCircle;

public Dartboard(double radius){

this.radius = radius;

insideCircle = 0;

outsideCircle = 0;

}

public void strike(Toss toss){

double x = toss.getX();

double y = toss.getY();

if(Math.sqrt(x*x + y*y) < radius)

insideCircle++;

else

outsideCircle++;

}

public double getFractionIn() {

double total = (double) (insideCircle + outsideCircle);

return (double) insideCircle/total;

}

}

class Toss{

private double x,y;

public Toss(double x, double y){

this.x = x;

this.y = y;

}

public double getX(){return x;}

public double getY(){return y;}

public static Toss getRandom(double radius){

double x,y;

double size = Math.random();

double sign = Math.random();

size = size * radius;

if(sign > 0.5)

x = size;

else

x = -size;

size = Math.random();

sign = Math.random();

size = size * radius;

if(sign > 0.5)

y = size;

else

y = -size;

return new Toss(x,y);

}

}

執行一下上述代碼,然后我們來驗證一下其效果如何...

How many darts shoud I toss at the board?1000000Pi is approximately 3.142028

可見所得到的結果較好地近似於圓周率 π 。

(本文完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值