歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

利用Java隨機數計算圓周率π

一、理論篇

1. 數學公式

圓面積公式:π*r*r,其中π為圓周率,r為圓半徑;

正方形面積公式:s*s,其中s為邊長;

勾股定理:a*a + b*b = c*c,其中a/b分別為直角三角形的兩個直角邊,c為斜邊。

2. 計算方法

考慮下圖,邊長為r的正方形內嵌了一個以r為半徑的1/4圓。

InsideCircle面積 = 以r為半徑的圓面積 / 4 = π*r*r/4

正方形面積 = r*r

所以, InsideCircle面積 / 正方形面積 = (π*r*r/4) / (r*r) = π/4

面由線組成,線由點組成。因此,如果有若干點均勻落入到正方形中,那麼落入InsideCircle的點的個數占總數的比率也將會是π/4,由此將會統計出π的值。

二、實戰篇

1. 散彈槍計算

具體方式為:制作一個如上圖一樣正方形木板,用散彈槍對著它一頓亂掃,最後統計彈孔個數和落點,從而得出π的值。

事實上,真的有研究人員做過這個腦洞大過黑洞的實驗,他們在 30857 個樣本中得到了 3.13 這個還算不錯的結果。

詳見:http://www.linuxidc.com/Linux/2015-01/111775.htm

2. Java隨機數計算

作為一個碼農,當然玩不起散彈槍這種高級玩具,那麼接下來就以代碼來玩一把。

具體思路是這樣的:r直接取值為1.0,還需要定義一個落在正方形中的所有點的個數PointNumber,每一個點都有一個坐標(x,y),x,y取值為0.0-1.0,利用Java隨機數生成每個點,然後用勾股定理判斷該點是落在圓內還是圓外,並統計落在圓內的點的個數InsideCircleNumber,那麼π=InsideCircleNumber/PointNumber*4。當然,如果只計算一次的話,可能誤差會較大,可以再增加一個計算次數CalcTimes,然後求平均值。

按照這樣的思路的計算結果如下:

PointNumber

CalcTimes

π

最接近π的值

10000

10000

3.141617279999959

3.1416

100000

10000

3.1415569599999684

3.1416

1000000

10000

3.1415845499999953

3.141592

10000000

10000

3.1415924761886806

3.1415928

附源代碼:
package com.test.pai;
import org.apache.commons.lang.math.RandomUtils;
public class CalcPai         
{           
    public static boolean inCircle(double x, double y)           
    {           
        return (y <= Math.sqrt(1 - x * x));           
    }
    public static double CalcPaiByPointNumber(long num)         
    {           
        double inCircleNum = 0.0;           
        for (long i = 0; i < num; i++)           
        {           
            if (CalcPai.inCircle(RandomUtils.nextDouble(), RandomUtils.nextDouble()))           
            {           
                inCircleNum++;           
            }           
        }
        double pai = inCircleNum * 4 / num;
        return pai;         
    }
    public static void main(String[] args)         
    {           
        double realPai = 3.14159265;           
        CurrResult currResult = new CurrResult(0.0, realPai, 0.0);           
        long times = 10000;           
        long num = 1000000;           
        for (long i = 1; i <= times; i++)           
        {
            double pai = CalcPai.CalcPaiByPointNumber(num);         
            currResult.setTotalPai(currResult.getTotalPai() + pai);           
            double diff = Math.abs(realPai - pai);           
            if (diff < currResult.getDifference())           
            {           
                currResult.setCurrPai(pai);           
                currResult.setDifference(diff);           
            }
            System.out.println("No." + i + "/" + times + "\t" + pai + "\t" + currResult.getCurrPai() + "\t"         
                    + currResult.getTotalPai() / i);           
        }
    }
}
 

Copyright © Linux教程網 All Rights Reserved