使用 Math.random 來生成隨機數在平常操做中是廣泛而且是簡單的。以下:javascript
let rnd = Math.random() * 10;
上述代碼的做用是生成 0~10
的隨機數。java
那麼,這些隨機數是出現的機率是均衡的嗎?
筆者沒辦法直接回答這個問題。由於生成的隨機數個數理論上是一個無窮大的數集,不過,能夠按數值大小範圍來估算數值的分佈是否平均:dom
let bucket = new Array(10).fill(0); let res = new Array(500000); // 作50萬次隨機數 for(let i = 0; i < 500000; ++i) { res[i] = Math.random() * 10; // 數值大小規類 let num = res[i]; for(let i = 0; i < 10; ++i) { if(num >= i * .1 && num < (i + 1) * .1) { ++bucket[i]; } } } bucket.forEach( (count, index) => { console.log(index * .1 + "~" + (index + 1) * .1 + "的機率:" + count / 500000) } )
如下是一次輸出結果:函數
結果顯示 Math.random() * 10
生成的數值分佈是比較均衡的。測試
可是,若是把「隨機數」改爲「隨機整數」。代碼改爲:spa
let rnd = Math.round(Math.random() * 10);
上面代碼是生成 0~10
的隨機整數。code
那麼,這些隨機整數是出現的機率是均衡的嗎?ip
筆者直觀上以爲是隨機的,可是實際狀況並非!測試代碼以下:rem
let res = new Array(11).fill(0); // 作一萬次隨機數 for(let i = 0; i < 500000; ++i) { ++res[Math.round(Math.random() * 10)]; } res.forEach((count, index) => console.log(index + "的機率:" + count / 500000))
如下是一次結果:it
不難發現,0
和 10
的機率是其它數值的一半左右,而其它數值的機率相差無幾。
Math.round 方法是形成「隨機整數」不均衡的緣由
Math.round/Math.ceil/Math.floor
這三個函數做用是使必定範圍內的實數轉換成同一個整數。以 Math.round 爲例以下:
從上圖能夠直觀地看到,頭尾兩數(0&10)的取值範圍是其它整數的一半!
生成隨機均衡整數的一種方案
其實,只須要保證取值範圍的長度一致便可以實現隨機均衡整數。如下是筆者實現的一種方案:
let res = new Array(11).fill(0); // 作一萬次隨機數 for(let i = 0; i < 500000; ++i) { ++res[Math.floor(Math.random() * 11)]; } res.forEach((count, index) => console.log(index + "的機率:" + count / 500000))
如下是一次輸出結果:
從結果上看分佈是均衡的。