摘要:另外,這幾篇幾個不錯的隨機生成隨機數采用對獲取的浮點數進行取整操作,也是同樣的問題,能取到左端點,卻無法取到右端點。
最近在琢磨內置對象Math的時候,參考了很多網上資料,不過我在Google中搜索js 隨機整數,出來很多博客文章,很遺憾,在我看來排名靠前的這些文章都是錯誤的。接下來我將會論證我這一觀點,同時把我所理解的Math.random()方法跟你分享。
在這篇文章中,作者給出了如下方法,根據他的文章描述,這個算法能產生start到end之間的隨機整數。
javascriptfunction rnd(start, end){ return Math.floor(Math.random() * (end - start) + start); }一個需要確認的問題
在說我的觀點之前,我希望先明確一件事情,設想別人跟你提了一個需求:
需要一個生成a到b之間隨機整數的方法。
這時候我覺得你至少需要跟對方確認一個問題:包不包括兩個端點,即a和b ?
(其實還有一些問題需要考慮的,比如傳入的a和b如果不是數字類型?如果是小數?如果是負數?如果a比b大?為了專注本文要討論的內容,我們假定傳入的a和b都是合法的正整數,且a<b。)
如果對方給你確認了,那是墜吼的;但是如果對方沒有確認,如何理解這一需求?我認為在對上述需求沒有更多說明的情況下,以下兩個是靠譜的理解:
既要包括端點a,也要包括端點b。
既不包括端點a,也不包括端點b。
所以,如果你實現的方法能獲取的只包含其中一個端點,我覺得這種實現是不太理想的,你再琢磨這句話:a到b之間的隨機整數。
如果你也認同我的這段論述,接下來回到開頭那個方法,看他能不能實現獲取從start到end之間的隨機整數;方法主體就一個運算表達式:
javascriptreturn Math.floor(Math.random() * (end - start) + start);
逐步分析:
javascriptMath.random(); //[0,1) Math.random()*(end-start); //[0,end-start); Math.random()*(end-start)+start; //[start,end); Math.floor(Math.random()*(end-start)+start); //{ x | x>=start,xMath.ceil(Math.random()*3);//得到1-3的整數 第一行,Math.random()方法返回的是0到1之間的浮點數,注意,__包括0,不包括1!__ECMA語言標準里明確規定了:
Returns a Number value with positive sign, greater than or equal to 0 but less than 1
所以,這篇博客,和這篇博客是不正確的;由于這兩篇占據結果第一頁的博文比較古老,我甚至在想是不是ECMA標準一開始不是這樣子的,然后查了一下,ECMA標準從第一個版本對random方法的規定就是現在這個樣子。
第二行,Math.random()*(end-start);則返回0到end-start之間的浮點數,包含0,不包含end-start。
第三行, Math.random()*(end-start)+start;返回start到end之間的浮點數,包含start,不包含end。
第四行,Math.floor(Math.random()*(end-start)+start);。這是最關鍵的一行,對上一行產生的浮點數進行向下取整,既然是向下取整,結果可能取到start,卻永遠取不到end。
根據前述理解,這樣的實現我認為是不合要求的。所以,這篇文章也是不正確的。
另外,這幾篇幾個不錯的JavaScript隨機...、js生成隨機數采用parseInt對獲取的浮點數進行取整操作,也是同樣的問題,能取到左端點,卻無法取到右端點。parseInt操作浮點數的效果相當于Math.floor()。勘誤:之前寫的上面這句話“parseInt操作浮點數的效果相當于Math.floor()”,我在看了這篇文章之后發現這句話是不對的,抱歉。但我的結論是不變的:Math.random()的結果范圍包括0,因此parseInt(Math.random())也可能取到0
而這一篇JavaScript random方法得到隨機整數,采用的是Math.ceil()方法進行向上取整,
javascript
這樣確實既能取到右端點,也能取到左端點,但是作者的左端點標錯了,這個是有可能能取到0的,盡管取到0的概率是無限趨近于0;
這樣引伸出另一個問題:取得的隨機整數范圍里,各整數出現的概率是否一致?
獲取概率問題 一個概率不均等的方法在之前有位老師給出的獲取隨機數方法是下面這樣(要求了必須包括端點);
javascriptfunction getRandom(n,m){ //省略特殊情形下的處理過程,比如n>m,或者n、m之一無法轉化為有效數字; return Math.round(Math.random()*(m-n)+n); }
一個獲取隨機整數的方法,如果不格外的聲明,我覺得有一個默認的條件應該是:
生成每個整數的概率應當是均等的;
根據第一部分的分析,這個方法能獲取的浮點數的范圍是n到m之間,包括n,不包括m;而這個方法中取整是采用Math.round()四舍五入;這樣的話:
當取出的結果x∈[n,n+0.5)時,會四舍五入為n;區間范圍為0.5,概率為0.5/(m-n)*100%;
當取出的結果x∈[n+0.5,n+1.5)時,會四舍五入為n+1;區間范圍為1,概率為1/(m-n)*100%;
當取出的結果x∈[n+1.5,n+2.5)時,會四舍五入為n+2;區間范圍為1,概率為1/(m-n)*100%;
......
當取出的結果x∈[m-0.5,m)時,會四舍五入為m;區間范圍為0.5,概率為0.5/(m-n)*100%;
通過以上分析,該算法確實可以達到目標,取到n到m之間的隨機整數,但是并不是每個整數出現的概率都是相等的,具體來說,取得兩邊端點的整數概率是其他數字的一半。所以,我認為這也是不夠完美的。
這樣的話,在寫一個獲得概率均等的隨機整數方法的時候,相信你知道應該注意些什么問題了吧。
總結總結一下,當我們在獲取隨機整數的時候,有兩個問題需要特別注意:
一定要仔細檢查兩邊端點是否是否能取到?是否與需求一致?
獲取到的每個整數的概率是否均等?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85809.html
摘要:目錄導語對象對象對象方法的應用日歷插件小結導語這是標準庫系列的第二篇文章,主要討論一下對象和對象,對象在平時處理一些數學操作時能起到事半功倍的作用,目前小羊接觸到的對象的使用場景是動畫制作對象作為關于時間的接口,能夠將其應用于制作和時間相關 目錄 導語 1. Math對象 2. Date對象 3. Date對象方法的應用——日歷插件; 4. 小結 導語 這是《JavaScript標準...
摘要:字符串與數字間的轉換結果結果結果結果注意會把一個類似于的字符串強制轉換成判斷是否為有效的數字某些方法如會返回一個特殊的值請注意第點中的注意此方法不完全適合判斷一個字符串是否是數字型小數轉整數結果四舍五入結果返回大于的最小整數結果返回小于的最 1.字符串與數字間的轉換 var i = 1; var str = i.toString(); //結果: 1 var str...
摘要:看完部分的源碼,首先迫不及待想跟大家分享的正是本文主題數組亂序。這是一道經典的前端面試題,給你一個數組,將其打亂,返回新的數組,即為數組亂序,也稱為洗牌問題。關于數組亂序,正確的解法應該是,復雜度。 前言 終于可以開始 Collection Functions 部分了。 可能有的童鞋是第一次看樓主的系列文章,這里再做下簡單的介紹。樓主在閱讀 underscore.js 源碼的時候,學到...
閱讀 791·2021-11-12 10:36
閱讀 3369·2021-09-08 10:44
閱讀 2742·2019-08-30 11:08
閱讀 1397·2019-08-29 16:12
閱讀 2672·2019-08-29 12:24
閱讀 895·2019-08-26 10:14
閱讀 683·2019-08-23 18:32
閱讀 1171·2019-08-23 17:52