iT邦幫忙

8

[筆記][JavaScript]用Math.random()取得亂數的技巧

HI!!先來向大家說聲新年快樂!!!每年只要到了這個時候,小弟我都會找幾個朋友到公益彩券店刮一個傾家蕩產,不過這樣一路走來,從一開始想要一夜致富到現在只想著不要輸太多就好XDD,而過年的時候公益彩卷總是會加碼一些彩卷的額外獎項,所以我們就來應景一下,試著做實做一個產生一組威力彩號碼,那廢話不多說,以下開始實做。

首先我們需要用到JS本身的Math.random()函式,這個函數會隨機產生出0~1之間的小數,如下例子:

Math.random(); //0.8961082300942438
Math.random(); //0.009676286758744546
Math.random(); //0.7722302289555816

但是他亂數產生小數並不是我們要的,那該如何讓他隨機產生整數呢?首先我們先觀察這個函數的規律,因為他會隨機產生0~1之間的小數,所以他會產生出的最大的數不會大於等於1也就是0.9999...9而最小的數不會等於0也就是0.0000...01,假設我們要讓他產生的範圍為威力彩可下注號碼(01~38),可以搭配另一個JS的內建函式Math.floor()來做到,這個函式會將所有的小數無條件捨去到比自身小的最大整數,也就是說當我們把Math.random()的結果放到Math.floor()中的時候,永遠會得到0,因為就算是Math.random()產生出的最大結果0.99...999也會被捨為0,如下例子:

Math.floor(Math.random());  //回傳0
Math.floor(0.99999999999);  //回傳0

那接下來就要同時使用Math.random()Math.floor()兩種方式來實做我們的function了,就我們剛才觀察出來的Math.random()他的最大值永遠不會大於等於1,也就是說,如果我將Math.random()產生出來的數去乘上2就會得到0~2之間的小數,乘上3就會得到0~3之間的小數,以此類推,所以利用這一點再搭配上Math.floor(),當我們把Math.random()*2放進Math.floor()中就會得到0或1的結果,因為Math.random()*2產生出來的值會是0.0000...02到1.9999...98之間的隨機小數,最小的被捨去會得到0,最大的被捨去又會得到1,以下我們看實做:

Math.floor(Math.random()*2); //回傳0或1
Math.floor(Math.random()*3); //回傳0或1或2
Math.floor(Math.random()*5); //回傳0或1或2或3或4
Math.floor(Math.random()*50); //回傳0或1或2或3...或49

根據上述的例子,我們可以先實做以下的function

function getRandom(x){
    return Math.floor(Math.random()*x);
};
getRandom(3); //會回傳0~2之間的隨機數字
getRandom(5); //會回傳0~4之間的隨機數字

其實上面的function已經和我們的目的非常接近了,只是function內還有兩個問題需要排除,第一個是我們要的範圍是不包括0的,第二個是他的範圍會是到「x-1」而不是到「x」,不過這並不是什麼大問題,因為我們只需要在得到的結果後方加上1就可以一次解決這兩個問題,如下:

function getRandom(x){
    return Math.floor(Math.random()*x)+1;
};
getRandom(3); //會回傳1(0+1)~3(2+1)之間的隨機數字
getRandom(5); //會回傳1(0+1)~5(4+1)之間的隨機數字

如此就達到我們的目標了!!去亂數產生1~x之間的整數,所以我們在稍微修飾一下就可以拿來產生一組威力彩的號碼了:

//宣告我們剛剛寫好的取亂數的function
function getRandom(x){
    return Math.floor(Math.random()*x)+1;
};
//再來寫產生威力彩號碼的function
function getPowerNum(){
    //首先我們先宣告一個字串,用來裝要回傳的結果
    var status = '第一區號碼為:';
    //宣告一個變數用來裝隨機產生的數字
    var n = 0;
    //一注威力彩號碼有6個所以我們讓迴圈跑六次
    for(i=0;i<=5;i++){
        //用indexOf判斷該數字之前有沒有出現過
        n = getRandom(38);
        if(status.indexOf(n)>0){
        //如果有出現過就重跑一次迴圈
        i-=1;
        continue;
        }
        else{
        //沒出現過的話就寫進字串裡
        status += n + ' ';
        };
    };
    //因為威力彩有分兩區,第二區為01~08隨機一數字,所以我們在回傳時加上。
    return status + '第二區號碼為:' + getRandom(8);
};

getPowerNum();
//回傳結果:"A組號碼為:19 11 2 30 20 8 B組數字為:2"

這麼一來就完成了我們最終的目的了,不過這只是基本的取亂數的方法,因為在這個例子都是從1~x選出隨機亂數,但是實務上我們遇到的需求可能千奇百怪,說不定會需要從x~y之間的隨機亂數,這個下次發文的時候再繼續實做從一個範圍中去產生亂數。

以上如果我有觀念錯誤或解釋不清楚的地方,還麻煩各位大大指點了,謝謝大家!

最後再向大家說聲新年快樂!!/images/emoticon/emoticon57.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
QQBoxy
iT邦新手 1 級 ‧ 2018-02-23 11:43:10

可以再加個UI跟History,
就可以變成抽獎小玩具了XD

神Q超人 iT邦研究生 5 級 ‧ 2018-02-23 22:59:02 檢舉

對哇 現在網路都一堆現成抽獎玩具了XD
也輪不到我處理/images/emoticon/emoticon02.gif

0
pulipuli
iT邦新手 5 級 ‧ 2019-11-05 11:31:49

實用

0

路過看到覺得很棒,謝謝

0
lemonno003
iT邦新手 5 級 ‧ 2022-07-07 21:59:30

我在另一個網站看到的函數返回範圍為[0,1)。

Math.random();
參數:此函數不接受任何參數。
返回值:math.random()函數返回範圍為[0,1),0(含)和1(不含)之間的浮點偽隨機數。

我要留言

立即登入留言