我该如何在 JavaScript 中生成在两个指定变量之间的随机整数,例如 x = 4
和 y = 8
会输出 4, 5, 6, 7, 8
中的任意一个?
我该如何在 JavaScript 中生成在两个指定变量之间的随机整数,例如 x = 4
和 y = 8
会输出 4, 5, 6, 7, 8
中的任意一个?
我在 W3Schools 上找到了这个简单的方法:
Math.floor((Math.random() * max) + min);
Math.random()
很快,适用于许多目的,但如果您需要加密安全值(它不安全),或者您需要来自完全均匀无偏分布的整数(其他答案中使用的乘法方法会比其他一些值稍微频繁地产生某些值),那么就不合适。
在这种情况下,我们可以使用crypto.getRandomValues()
生成安全整数,并拒绝我们无法将其均匀映射到目标范围的任何生成值。这会更慢,但除非您要生成极大量的值,否则不应该有太大影响。
为了澄清偏向分布问题,请考虑这样一个情况:我们想生成介于1和5之间的值,但是我们有一个随机数生成器,它会生成介于1和16之间的值(4位值)。我们希望有相同数量的生成值映射到每个输出值,但是16不能被5整除:留下余数1。因此,我们需要拒绝可能生成的1个值,只有在获得15个较小的值并且能够均匀映射到我们的目标范围时才继续执行。 我们的行为可能看起来像是这样的伪代码:
Generate a 4-bit integer in the range 1-16.
If we generated 1, 6, or 11 then output 1.
If we generated 2, 7, or 12 then output 2.
If we generated 3, 8, or 13 then output 3.
If we generated 4, 9, or 14 then output 4.
If we generated 5, 10, or 15 then output 5.
If we generated 16 then reject it and try again.
number
类型可以表示的最大常规整数大小。 (如果需要更大的范围,可以修改为使用BigInt
。)无论选择什么范围,被拒绝的生成值的比例总是小于0.5,所以期望的拒绝数量总是小于1.0,并且通常接近于0.0;您不需要担心它会永远循环下去。
const randomInteger = (min, max) => {
const range = max - min;
const maxGeneratedValue = 0xFFFFFFFF;
const possibleResultValues = range + 1;
const possibleGeneratedValues = maxGeneratedValue + 1;
const remainder = possibleGeneratedValues % possibleResultValues;
const maxUnbiased = maxGeneratedValue - remainder;
if (!Number.isInteger(min) || !Number.isInteger(max) ||
max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) {
throw new Error('Arguments must be safe integers.');
} else if (range > maxGeneratedValue) {
throw new Error(`Range of ${range} (from ${min} to ${max}) > ${maxGeneratedValue}.`);
} else if (max < min) {
throw new Error(`max (${max}) must be >= min (${min}).`);
} else if (min === max) {
return min;
}
let generated;
do {
generated = crypto.getRandomValues(new Uint32Array(1))[0];
} while (generated > maxUnbiased);
return min + (generated % possibleResultValues);
};
console.log(randomInteger(-8, 8)); // -2
console.log(randomInteger(0, 0)); // 0
console.log(randomInteger(0, 0xFFFFFFFF)); // 944450079
console.log(randomInteger(-1, 0xFFFFFFFF));
// Error: Range of 4294967296 covering -1 to 4294967295 is > 4294967295.
console.log(new Array(12).fill().map(n => randomInteger(8, 12)));
// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]
在最小值和最大值之间随机生成一个整数:
function randomRange(low, high) {
var range = (high-low);
var random = Math.floor(Math.random()*range);
if (random === 0) {
random += 1;
}
return low + random;
}
这并不是最优雅的解决方案,但可以快速实现。
if
),可以说随机数的分布情况如何? - Peter Mortensenfunction genRandom(length)
{
const t1 = new Date().getMilliseconds();
var min = "1", max = "9";
var result;
var numLength = length;
if (numLength != 0)
{
for (var i = 1; i < numLength; i++)
{
min = min.toString() + "0";
max = max.toString() + "9";
}
}
else
{
min = 0;
max = 0;
return;
}
for (var i = min; i <= max; i++)
{
// Empty Loop
}
const t2 = new Date().getMilliseconds();
console.log(t2);
result = ((max - min)*t1)/t2;
console.log(result);
return result;
}
// Get random number within provided base + exponent
// By Goran Biljetina --> 2012
function isEmpty(value) {
return (typeof value === "undefined" || value === null);
}
var numSeq = new Array();
function add(num, seq) {
var toAdd = new Object();
toAdd.num = num;
toAdd.seq = seq;
numSeq[numSeq.length] = toAdd;
}
function fillNumSeq (num, seq) {
var n;
for(i=0; i<=seq; i++) {
n = Math.pow(num, i);
add(n, i);
}
}
function getRandNum(base, exp) {
if (isEmpty(base)) {
console.log("Specify value for base parameter");
}
if (isEmpty(exp)) {
console.log("Specify value for exponent parameter");
}
fillNumSeq(base, exp);
var emax;
var eseq;
var nseed;
var nspan;
emax = (numSeq.length);
eseq = Math.floor(Math.random()*emax) + 1;
nseed = numSeq[eseq].num;
nspan = Math.floor((Math.random())*(Math.random()*nseed)) + 1;
return Math.floor(Math.random()*nspan) + 1;
}
console.log(getRandNum(10, 20), numSeq);
//Testing:
//getRandNum(-10, 20);
//console.log(getRandNum(-10, 20), numSeq);
//console.log(numSeq);
使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
/*
Assuming that window.crypto.getRandomValues
is available, the real range would be from
0 to 1,998 instead of 0 to 2,000.
See the JavaScript documentation
for an explanation:
https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
*/
var array = new Uint8Array(2);
window.crypto.getRandomValues(array);
console.log(array[0] + array[1]);
</script>
</body>
</html>
Uint8Array创建一个由数字填充的数组,最多可达三位数,即最大值为999。这段代码非常简短。
Uint8Array
的语法高亮确实很奇怪。” - Peter MortensenIonuț G. Stan写了一个很好的答案,但对我来说有点太复杂了。因此,我在Jason Anello的解释中找到了更简单的相同概念的解释。
注意:在阅读Jason的解释之前,您唯一需要知道的重要事情是“截断”的定义。他在描述Math.floor()
时使用该术语。牛津词典将“截断”定义为:
通过切断顶部或末端缩短(某物)。
maxNum = 8,
minNum = 4
console.log(Math.floor(Math.random() * (maxNum - minNum) + minNum))
console.log(Math.floor(Math.random() * (8 - 4) + 4))
这将在控制台中记录介于4和8之间(包括4和8)的随机数。
maxNum = 2, minNum = 1
不起作用,结果总是1。实际上,我认为任何仅相差1个数字的min和max都是一样的;较低的边界始终是结果。 - devklickrandUpTo
的函数,接受一个数字并返回在 0 和该数字之间的随机整数:var randUpTo = function(num) {
return Math.floor(Math.random() * (num - 1) + 0);
};
一个名为randBetween
的函数,接受两个代表范围的数字,并返回这两个数字之间的随机整数:
var randBetween = function (min, max) {
return Math.floor(Math.random() * (max - min - 1)) + min;
};
一个名为randFromTill
的函数,接受两个数字表示范围,并返回介于最小值(包括)和最大值(不包括)之间的随机数。
var randFromTill = function (min, max) {
return Math.random() * (max - min) + min;
};
randFromTo
的函数,接受两个数字表示范围,并返回在最小值(包括)和最大值(包括)之间的随机整数:var randFromTo = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
let randomNumber = function(first, second) {
let number = Math.floor(Math.random()*Math.floor(second));
while(number < first) {
number = Math.floor(Math.random()*Math.floor(second));
}
return number;
}
do-while
而不是 while
即可。 - Javi Marzánfirst
是1,000,000,000,而second
是1,000,000,042,那么这将非常慢。也许可以在你的答案中添加一些警告语句?甚至可以添加一些基准测试来演示性能影响何时变得显著(以量化它)?(但是不要包含"Edit:"、"Update:"或类似的内容——答案应该看起来像是今天写的。) - Peter Mortensen