有趣的問題:給你一個生成0到1之間隨機數的函數,請求出圓周率π

來源

這是一道我在看 Youtube 時無心間發現的問題,原視頻連接:https://www.youtube.com/watch...c++

問題是:給你一個生成0到1之間隨機數的函數,請求出圓周率 π編程

第一眼看上去彷彿是一個徹底沒頭腦的問題,可是仔細一想,就能夠使用一點編程能力和初中的數學知識解決。vim

思路

思路應該是去尋找兩個東西的交匯點,一個隨機數,是一個數字,也能夠是數軸上的一個點。兩個隨機數,就是兩個數軸上的點,或者是一個座標軸上的點(r1, r2),若是調用無數次的隨機數,就能夠得到無數個座標軸上的點。dom

圓周率,咱們必需要找到一個使用了圓周率的東西,很容易想到圓的面積和周長。函數

如今咱們有了無數個在座標軸上的點圓的面積圓的周長。emmmm……有想到什麼嗎?oop

也許咱們應該畫一個圖。spa

image.png

也許咱們應該把圓畫上去,應該會幫助咱們思考。code

image.png

OK,知道了,全部的點會落在正方形(0,0,1,1) 的範圍內,其中有一部分會落在圓的範圍內,若是咱們統計落在圓內的點的個數,記爲 N,那麼 N 與總點數 M 的比值,應該是等於圓的面積比上正方形的面積。視頻

列下公式應該是:blog

$$ r = 1/2 $$
$$\frac{N}{M} = \frac{\pi r^2}{(2r)^2}$$

把公式化簡一下,變成:
$$\pi = 4 * N / M$$

爲了編程中方便計算任意點距離圓心的距離,能夠這樣理解這個機率:
image.png

公式中的關係依然成立。

編程實現

fun main() {
    var times = 100L
    for (i in 1..9) {
        println("loop: $times pi: ${getPi(times)}")
        times *= 10
    }
}

fun getPi(count: Long): Double {
    var c = 0
    for (i in 0 until count) {
        val x = Math.random()
        val y = Math.random()

        if (x * x + y * y < 1) {
            c++
        }
    }
    return 4.0 * c / count
}

運行結果:

loop: 100 pi: 3.24
loop: 1000 pi: 3.168
loop: 10000 pi: 3.1528
loop: 100000 pi: 3.14348
loop: 1000000 pi: 3.141964
loop: 10000000 pi: 3.1414304
loop: 100000000 pi: 3.14131604
loop: 1000000000 pi: 3.141585632
loop: 10000000000 pi: 3.1415885784
相關文章
相關標籤/搜索