js 為何范圍內隨機取整要用floor,而不是ceil或者round呢


 壹 ❀ 引

我在如何使用js取任意范圍內隨機整數這篇博客中,列舉並分析了取[n,m)與[n,m]范圍內整數的通用方法,並在文章結果留了一個疑問;為什么通用方法中取整操作,我們使用Math.floor()而不是Math.ceil()或者Math.round()方法呢?

知其然更知其所以然,加上在GitHub中那道筆試題答案下,不少網友的答案使用了round或ceil方法來取整,說明不少人對於隨機取整為何一定要用floor方法是沒有一個深刻理解的,那么本文就對於這個問題展開分析。

 貳 ❀ round ceil floor有何區別

在弄懂這個問題前,我們先將這三個方法的區別說清楚,它們都是JavaScript提供的數字取整方法,但卻有着本質區別。

1.關於Math.round()

Math.round()的含義是將一個數字四舍五入為最接近的整數,四舍五入大家不會陌生,一個數字如果是4那就舍棄掉,如果是5,那就進一。

Math.round(0.5); //1
Math.round(1.2); //1
Math.round(2.41); //2
Math.round(-3.55); //-4

2.關於Math.ceil()

Math.ceil()的含義是向上取整,說直白點,就是得到一個大於等於且最接近自己的整數,不難理解。

Math.ceil(0); //0
Math.ceil(1.2); //2
Math.ceil(2.41); //3
Math.ceil(-3.55); //-3

3.關於Math.floor()

Math.floor()剛好與Math.ceil()相反,這是一對冤家,它表示的是向下取整,也就是找小於等於且最接近自己的整數

Math.floor(0); //0
Math.floor(1.2); //1
Math.floor(2.41); //2
Math.floor(-3.55); //-4

 叄 ❀ 隨機整數概率問題

1.使用round的問題

我們知道,當取[0,5]范圍內隨機整數時,從概率角度,我們是希望每個隨機數出現概率是相同的,那么當我們使用round方法會有什么問題呢?

round的作用是四舍五入取整,為了不那么復雜,我們將數字范圍划分為0 -- 0.5 -- 1 -- 1.5 -- 2 -- 2.5 -- 3 -- 3.5 -- 4 -- 4.5 -- 5 這幾個階段。

很明顯,當范圍是0 -- 0.499之前被四舍五入為0,而0.5 -- 11 -- 1.4999可四舍五入為1,同理,2階段,3階段,4階段都是前后兩個范圍,4.5 -- 5可四舍五入為5。

由此可以統計出1,2,3,4出現的概率要整整比0,5兩個邊界數字出現的概率高百分之50,我們做個簡單的測試:

Math.floor(Math.random() * 6);

這段代碼,是取[0,5]范圍的隨機整數,我們將floor改為round,簡單修改邏輯(因為四舍五入,這里改為乘以5),查看每五次取得數字的概率:

function randomArr() {
    let arr = [],
        length = 5;
    while (length--) {
        arr.push(Math.round(Math.random() * 5));
    };
    console.log(arr);
};
setInterval(function () {
    randomArr();
}, 1000);

如上圖,一眼掃下來出現0與5的概率,普遍比1,2,3,4要低,很明顯這對於0與5兩個邊界數字是不公平的。

2.使用ceil取整的問題

有了上面的分析,ceil就好理解多了,同樣是[0,5]范圍取隨機整數,我看同樣做范圍拆分。

由於是ceil是向上取整,只有是0時,才是0;只要超過0,0.1甚至0.0001都會向上取整變成1,同理,2,3,4,5概率都會相同,我們可以得出使用ceil對於0是極不公平的,我們將上面的代碼中的round改為ceil:

想要隨機取整的數字是0的概率,簡直比中彩票頭等獎還低,畢竟0-1范圍內的隨機數字組合可以說無數個,外加上還有2,3,4,5幾個數字,這下總知道為啥不能用ceil了吧。

3.使用floor為什么可以

floor因為是向下取整,0-0.999之前都是0,1-1.999之前都是1,每個數字概率相同。

所以我們取[0-5]范圍內整數時,使用的是Math.random() * 6,得到的范圍就是[0-5.999..],在通過下下取整,也就達到取[0-5]的目的了。

4.使用ceil取整后減去1模擬floor?

不對啊,向下取整概率相同,我向上取整不也一樣?求[0-5]范圍時,我能不能利用向上取整,求一個[1-6]再減去1呢?很明顯不行。

0.1-0.999向上取整是1,1.1-1.999向上取整是2,我們這個基礎上減去一個1,想法是好的,但這個想法忽略了比中彩票還難出現的數字0,只要0出現,我們根據通用想法減去1,那就是-1了。

Math.ceil(Math.random() * 6) - 1

這段代碼貌似能正常取到0-5范圍的任意整數,其實當0出現時,就BUG了,雖然我們不知道0什么時候會出現。

 肆 ❀ 總

那么文章到這,我們大概知道了這幾個知識點:

1.round floor ceil的作用與區別

2.為什么取范圍隨機整數使用floor而不是round或者ceil

3.利用floor的思想模擬了ceil減一的做法,結果行不通

那么到這,算是給文章開頭的問題解答疑惑了,現在你知道為什么不能使用round或者ceil取隨機整數了嗎?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM