我怎样才能在两个指定的变量之间生成随机的整数,例如,x = 4
和y = 8
会输出4, 5, 6, 7, 8
中的任何一个?
在Mozilla开发者网络网页上有一些例子。
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Math.random()
返回0(包括)和1(不包括)之间的Number
。所以我们有一个这样的区间。
[0 .................................... 1)
现在,我们想要一个介于min'(包括)和
max'(排除)之间的数字。
[0 .................................... 1)
[min .................................. max)
我们可以使用Math.random
来获得[min, max]区间内的对应数。但是,首先我们应该从第二个区间中减去`min',把这个问题稍稍考虑一下。
[0 .................................... 1)
[min - min ............................ max - min)
这就得到了。
[0 .................................... 1)
[0 .................................... max - min)
我们现在可以应用Math.random
,然后计算出相应的结果。让我们选择一个随机数。
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
因此,为了找到`x',我们会做。
x = Math.random() * (max - min);
别忘了把`min'加回去,这样我们就能得到一个在[min, max]区间的数字。
x = Math.random() * (max - min) + min;
这就是MDN的第一个函数。第二个函数,返回min'和
max'之间的一个整数,两者都包括在内。
现在为了得到整数,你可以使用round
,ceil
或floor
。
你可以使用Math.round(Math.random() * (max - min))+ min",但是这将会得到一个非平均分布。
min和
max`都只有大约一半的机会滚动。
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
如果把 "最大 "排除在区间之外,它的出牌机会甚至比 "最小 "更少。
用`Math.floor(Math.random() * (max - min +1))+ min",你就有一个完全均匀的分布。
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
你不能在该等式中使用ceil()
和-1
,因为max
现在的机会略少,但你也可以滚出(不想要的)min-1
的结果。
function getRandomizer(bottom, top) {
return function() {
return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
}
}
用法。
var rollDie = getRandomizer( 1, 6 );
var results = ""
for ( var i = 0; i<1000; i++ ) {
results += rollDie() + " "; //make a string filled with 1000 random numbers in the range 1-6.
}
故障。
我们正在返回一个函数(借用函数式编程),当被调用时,将返回一个介于bottom
和top
之间的随机整数,包括在内。我们说'包容'是因为我们想把底部和顶部都包括在可以返回的数字范围内。这样,getRandomizer( 1, 6 )
将返回1、2、3、4、5或6。
(底部是较低的数字,顶部是较大的数字)
Math.random() * ( 1 + top - bottom )
Math.random()
返回一个介于0和1之间的随机双数,如果我们用它乘以1再加上top
和bottom
之间的差值,我们会得到一个介于0
和1+b-a
之间的双数。
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor
将数字向下四舍五入到最接近的整数。所以我们现在有了0'和
top-bottom'之间所有的整数。1看起来很混乱,但它需要存在,因为我们一直在向下舍入,所以没有它的话,实际上永远不会达到顶部的数字。我们生成的随机小数需要在0
到(1+top-bottom)
的范围内,所以我们可以向下取整,得到0
到top-bottom
范围内的一个int。
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
前面的例子中的代码给了我们一个在0
和top-bottom
范围内的整数,所以我们现在需要做的就是在这个结果上加上bottom
,得到一个在bottom
和top
范围内的整数。
注意:如果你先传入一个非整数或更大的数字,你会得到不理想的行为,但除非有人要求,否则我不打算深入研究参数检查代码,因为它与原问题的意图相去甚远。
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
要测试这个函数,以及这个函数的变化,请将下面的HTML/JavaScript保存到一个文件中,然后用浏览器打开。 该代码将产生一个*图,显示100万次函数调用的分布。 该代码还将记录边缘情况,因此,如果该函数产生的值大于最大值或小于最小值,你将知道它。
<html>
<head>
<script type="text/javascript">
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
var min = -5;
var max = 5;
var array = new Array();
for(var i = 0; i <= (max - min) + 2; i++) {
array.push(0);
}
for(var i = 0; i < 1000000; i++) {
var random = getRandomInt(min, max);
array[random - min + 1]++;
}
var maxSample = 0;
for(var i = 0; i < max - min; i++) {
maxSample = Math.max(maxSample, array[i]);
}
//create a bar graph to show the sample distribution
var maxHeight = 500;
for(var i = 0; i <= (max - min) + 2; i++) {
var sampleHeight = (array[i]/maxSample) * maxHeight;
document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px"> [' + (i + min - 1) + ']: '+array[i]+'</span> ');
}
document.write('<hr/>');
</script>
</head>
<body>
</body>
</html>