在JavaScript語言里有個 Math.random() 隨機函數,用於生成指定範圍內的隨機數。 #### Math.random()函數 根據官方的定義: **Math.random()** 函數返回一個浮點數, 偽隨機數在範圍[0,1),也就是說,從0(包括0)往上,但是不包括1(排除1), ...
在JavaScript語言里有個 Math.random() 隨機函數,用於生成指定範圍內的隨機數。
Math.random()函數
根據官方的定義: Math.random() 函數返回一個浮點數, 偽隨機數在範圍[0,1),也就是說,從0(包括0)往上,但是不包括1(排除1),然後您可以縮放到所需的範圍。實現將初始種子選擇到隨機數生成演算法;它不能被用戶選擇或重置。
也就是說 random() 方法可返回介於 0 ~ 1 之間的一個隨機數。比如:0.9322870363051519
、0.08182448197313485
、0.6718927278167157
,每次調用它會返回一個含16位小數的隨機浮點數。
我們日常代碼過程中實際上是需要生成整數,或是指定區間的隨機數,這就需要對它封裝改造一下了。常見的封裝改造有以下幾種。
隨機整數:floor + random
示例:生成隨機整數,傳入參數是最大值(不包括),即返回值是 [0, max)
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
console.log(getRandomInt(3));
// expected output: 0, 1 or 2
console.log(getRandomInt(1));
// expected output: 0
指定區間的隨機數(一)
示例:這個例子返回了一個在指定值之間的隨機數 [min, max)。這個值不小於 min(有可能等於),並且小於(不等於)max。
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
console.log(getRandomArbitrary(1,3));
// expected output: 1.0501238302537486,1.9956248025522734,2.7839421306375227 ……
指定區間的隨機數(二)
示例:這個例子返回了一個在指定值之間的隨機整數 [min, max)。這個值不小於 min (如果 min 不是整數,則不小於 min 的向上取整數),且小於(不等於)max。
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值
}
console.log(getRandomInt(1,3));
// expected output: 1 or 2
也許很容易想到用 Math.round() 來實現,但是這會導致你的隨機數處於一個不均勻的分佈,這可能不符合你的需求。
指定區間的隨機數(三)
上一個例子提到的函數 getRandomInt() 結果範圍包含了最小值,但不含最大值。如果你的隨機結果需要同時包含最小值和最大值,怎麼辦呢? getRoundRandom() 函數可以實現得到一個兩數之間的隨機整數,包括兩個數在內。
示例:這個例子返回了一個在指定值之間的隨機整數 [min, max]。這個值不小於 min (如果 min 不是整數,則不小於 min 的向上取整數),且不大於max(如果 max 不是整數,則不小於 max 的向下取整數)。
function getRoundRandom(min, max){
return Math.round(Math.random()*(max-min))+min;
}
console.log(myRoundRandom(1,3));
// expected output: 1, 2 or 3
需要註意:Math.round() 函數返回一個數字四捨五入後最接近的整數。它取整的結果分佈不均,大概成正泰分佈。驗證:var num = getRoundRandom(0, 5);
生成5輪,每輪10000個結果分佈如下:
指定區間的隨機數(四)
得到一個兩數之間的隨機整數,包括兩個數在內。如果想概率分佈均勻一點可以使用 Math.trunc()
Math.trunc() 方法會將數字的小數部分去掉,只保留整數部分。Math.trunc() 的執行邏輯很簡單,僅僅是刪除掉數字的小數部分和小數點,不管參數是正數還是負數。傳入該方法的參數會被隱式轉換成數字類型。
示例:這個例子返回了一個在指定值之間的隨機整數 [min, max]。這個值不小於 min,且不大於max。
function getTruncRandom(min, max){
return Math.trunc(Math.random()*(max-min+1))+min;
}
console.log(getTruncRandom(1,3));
// expected output: 1, 2 or 3
可以簡寫:const getTruncRandom=(min,max)=>Math.trunc(Math.random()*(max-min+1)+min);
驗證:var num = getTruncRandom(0, 5);
生成5輪,每輪10000個結果分佈如下:
指定區間的隨機數(五)
前面例子提到的函數 getRandomInt() 結果範圍包含了最小值,但不含最大值。如果你的隨機結果需要同時包含最小值和最大值,怎麼辦呢? getRandomIntInclusive() 函數可以實現得到一個兩數之間的隨機整數,包括兩個數在內。
示例:這個例子返回了一個在指定值之間的隨機整數 [min, max]。這個值不小於 min (如果 min 不是整數,則不小於 min 的向上取整數),且不大於max(如果 max 不是整數,則不小於 max 的向下取整數)。
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random()*(max-min+1))+min; //含最大值,含最小值
}
console.log(getRandomIntInclusive(1,3));
// expected output: 1, 2 or 3
驗證:var num = getRandomIntInclusive(0, 5);
生成5輪,每輪10000個結果分佈如下:
總結
1,實驗三採用round + random方式最終驗證隨機結果分佈不均衡,不予採用;
2,實驗四、實驗五最終驗證隨機結果分佈接近均衡,均可以採用;
3,實驗四利用 trunc + random 實現方式簡潔,運算次數更少,推薦採用;
附件代碼:生成5輪,每輪10000個結果分佈
<script>
// round + random()函數
function getRoundRandom(min, max){
return Math.round(Math.random()*(max-min))+min;
/* 實驗結果
游戲開始:zero = 0 one =0 two =0 three =0 four =0 five=0
游戲結束:zero = 1034 one =2011 two =1965 three =2004 four =1978 five=1008
游戲結束:zero = 978 one =2097 two =1967 three =1947 four =2062 five=949
游戲結束:zero = 1083 one =2066 two =1933 three =1908 four =1986 five=1024
游戲結束:zero = 994 one =1974 two =2092 three =1918 four =1967 five=1055
游戲結束:zero = 1010 one =1979 two =2086 three =1970 four =1944 five=1011
*/
}
// trunc + random()函數
function getTruncRandom(min, max){
return Math.trunc(Math.random()*(max-min+1))+min;
/* 實驗結果
游戲開始:zero = 0 one =0 two =0 three =0 four =0 five=0
游戲結束:zero = 1752 one =1607 two =1636 three =1631 four =1650 five=1724
游戲結束:zero = 1667 one =1660 two =1696 three =1654 four =1646 five=1677
游戲結束:zero = 1708 one =1658 two =1658 three =1724 four =1619 five=1633
游戲結束:zero = 1688 one =1620 two =1689 three =1664 four =1664 five=1675
游戲結束:zero = 1737 one =1644 two =1655 three =1656 four =1694 five=1614
*/
}
// ceil + floor + random()函數
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
function guess(){
var zero = one = two = three = four = five = 0; // 記錄每個數出現次數
console.log('游戲開始:zero = '+zero+' one ='+one+' two ='+two+' three ='+three+' four ='+four+' five='+five);
for(var i=0; i<10000; i++)
{
// 自定義生成隨機數
// var num = getRoundRandom(0, 5);
// var num = getTruncRandom(0, 5);
var num = getRandomIntInclusive(0, 5);
// 對結果類型計數
switch(num){
case 0: zero++; break;
case 1: one++; break;
case 2: two++; break;
case 3: three++; break;
case 4: four++; break;
case 5: five++; break;
default: console.error('生成數字錯誤 num='+num);
}
}
// 該輪結束輸出結果類型計數
console.log('游戲結束:zero = '+zero+' one ='+one+' two ='+two+' three ='+three+' four ='+four+' five='+five);
}
guess();
</script>
【完】