一、理論篇
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.techug.com/compute-pi-with-gun
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 double CalcPaiByPointNumber(long num) double pai = inCircleNum * 4 / num; return pai; public static void main(String[] args) double pai = CalcPai.CalcPaiByPointNumber(num); System.out.println("No." + i + "/" + times + "\t" + pai + "\t" + currResult.getCurrPai() + "\t" } } |