Javascript 生成 0 到 'x' 之间的唯一随机数(整数)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8378870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generating unique random numbers (integers) between 0 and 'x'
提问by benhowdle89
I need to generate a set of unique (no duplicate) integers, and between 0 and a given number.
我需要生成一组唯一的(没有重复的)整数,并且介于 0 和给定的数字之间。
That is:
那是:
var limit = 10;
var amount = 3;
How can I use Javascript to generate 3 unique numbers between 1 and 10?
如何使用 Javascript 生成 1 到 10 之间的 3 个唯一数字?
回答by Rob W
Use the basic Math
methods:
使用基本Math
方法:
Math.random()
returns a random number between 0 and 1 (including 0, excluding 1).- Multiply this number by the highest desired number (e.g. 10)
Round this number downward to its nearest integer
Math.floor(Math.random()*10) + 1
Math.random()
返回 0 到 1 之间的随机数(包括 0,不包括 1)。- 将此数字乘以所需的最高数字(例如 10)
将此数字向下舍入为其最接近的整数
Math.floor(Math.random()*10) + 1
Example:
例子:
//Example, including customisable intervals [lower_bound, upper_bound)
var limit = 10,
amount = 3,
lower_bound = 1,
upper_bound = 10,
unique_random_numbers = [];
if (amount > limit) limit = amount; //Infinite loop if you want more unique
//Natural numbers than exist in a
// given range
while (unique_random_numbers.length < limit) {
var random_number = Math.floor(Math.random()*(upper_bound - lower_bound) + lower_bound);
if (unique_random_numbers.indexOf(random_number) == -1) {
// Yay! new random number
unique_random_numbers.push( random_number );
}
}
// unique_random_numbers is an array containing 3 unique numbers in the given range
回答by Llamageddon
Math.floor(Math.random() * (limit+1))
Math.random()
generates a floating point number between 0 and 1, Math.floor()
rounds it down to an integer.
Math.random()
生成一个介于 0 和 1 之间的浮点数,Math.floor()
并将其向下舍入为整数。
By multiplying it by a number, you effectively make the range 0..number-1
. If you wish to generate it in range from num1
to num2
, do:
通过将它乘以一个数字,您可以有效地创建 range 0..number-1
。如果您希望在从num1
到 的范围内生成它num2
,请执行以下操作:
Math.floor(Math.random() * (num2-num1 + 1) + num1)
To generate more numbers, just use a for loop and put results into an array or write them into the document directly.
要生成更多数字,只需使用 for 循环并将结果放入数组或直接将它们写入文档。
回答by Bakudan
function generateRange(pCount, pMin, pMax) {
min = pMin < pMax ? pMin : pMax;
max = pMax > pMin ? pMax : pMin;
var resultArr = [], randNumber;
while ( pCount > 0) {
randNumber = Math.round(min + Math.random() * (max - min));
if (resultArr.indexOf(randNumber) == -1) {
resultArr.push(randNumber);
pCount--;
}
}
return resultArr;
}
Depending on range needed the method of returning the integer can be changed to: ceil(a,b], round[a,b], floor[a,b), for (a,b) is matter of adding 1 to min with floor.
根据所需的范围,返回整数的方法可以更改为:ceil(a,b], round[a,b], floor[a,b), for (a,b) 是将 1 添加到 min 的问题地面。
回答by P?l Brattberg
Math.floor(Math.random()*limit)+1
回答by Neeta
for(i = 0;i <amount; i++)
{
var randomnumber=Math.floor(Math.random()*limit)+1
document.write(randomnumber)
}
回答by Ash Burlaczenko
Something like this
像这样的东西
var limit = 10;
var amount = 3;
var nums = new Array();
for(int i = 0; i < amount; i++)
{
var add = true;
var n = Math.round(Math.random()*limit + 1;
for(int j = 0; j < limit.length; j++)
{
if(nums[j] == n)
{
add = false;
}
}
if(add)
{
nums.push(n)
}
else
{
i--;
}
}
回答by Rory O'Kane
Here's another algorithm for ensuring the numbers are unique:
这是确保数字唯一的另一种算法:
- generate an array of all the numbers from 0 to x
- shuffle the array so the elements are in random order
- pick the first n
- 生成从 0 到x的所有数字的数组
- 对数组进行洗牌,使元素按随机顺序排列
- 选择第一个n
Compared to the method of generating random numbers until you get a unique one, this method uses more memory, but it has a more stable running time – the results are guaranteed to be found in finite time. This method works better if the upper limit is relatively low or if the amount to take is relatively high.
与生成随机数直到得到唯一数的方法相比,这种方法使用更多的内存,但它的运行时间更稳定——保证在有限的时间内找到结果。如果上限相对较低或采取的金额相对较高,则此方法效果更好。
My answer uses the Lodashlibrary for simplicity, but you could also implement the algorithm described above without that library.
为简单起见,我的回答使用了Lodash库,但您也可以在没有该库的情况下实现上述算法。
// assuming _ is the Lodash library
// generates `amount` numbers from 0 to `upperLimit` inclusive
function uniqueRandomInts(upperLimit, amount) {
var possibleNumbers = _.range(upperLimit + 1);
var shuffled = _.shuffle(possibleNumbers);
return shuffled.slice(0, amount);
}
回答by ashleedawg
These answers either don't give uniquevalues, or are so long(one even adding an external library to do such a simple task).
这些答案要么没有给出唯一值,要么太长(甚至添加了一个外部库来完成如此简单的任务)。
1. generate a random number.
2. if we have this random already then goto 1, else keep it.
3. if we don't have desired quantity of randoms, then goto 1.
1. 生成一个随机数。
2. 如果我们已经有了这个随机数,则转到1,否则保留它。
3. 如果我们没有所需的随机数,则转到1。
function uniqueRandoms(qty, min, max){
var rnd, arr=[];
do { do { rnd=Math.floor(Math.random()*max)+min }
while(arr.includes(rnd))
arr.push(rnd);
} while(arr.length<qty)
return arr;
}
//generate 5 unique numbers between 1 and 10
console.log( uniqueRandoms(5, 1, 10) );
...and a compressed version of the same function:
...以及相同功能的压缩版本:
function uniqueRandoms(qty,min,max){var a=[];do{do{r=Math.floor(Math.random()*max)+min}while(a.includes(r));a.push(r)}while(a.length<qty);return a}
function uniqueRandoms(qty,min,max){var a=[];do{do{r=Math.floor(Math.random()*max)+min}while(a.includes(r));a.push(r)}while(a.length<qty);return a}
回答by Oleg Zarevennyi
Just as another possible solution based on ES6 Set("arr. that can contain unique values only").
就像另一种基于ES6 Set 的可能解决方案(“只能包含唯一值的 arr.”)。
Examples of usage:
用法示例:
// Get 4 unique rnd. numbers: from 0 until 4 (inclusive):
getUniqueNumbersInRange(4, 0, 5) //-> [5, 0, 4, 1];
// Get 2 unique rnd. numbers: from -1 until 2 (inclusive):
getUniqueNumbersInRange(2, -1, 2) //-> [1, -1];
// Get 0 unique rnd. numbers (empty result): from -1 until 2 (inclusive):
getUniqueNumbersInRange(0, -1, 2) //-> [];
// Get 7 unique rnd. numbers: from 1 until 7 (inclusive):
getUniqueNumbersInRange(7, 1, 7) //-> [ 3, 1, 6, 2, 7, 5, 4];
The implementation:
实施:
function getUniqueNumbersInRange(uniqueNumbersCount, fromInclusive, untilInclusive) {
// 0/3. Check inputs.
if (0 > uniqueNumbersCount) throw new Error('The number of unique numbers cannot be negative.');
if (fromInclusive > untilInclusive) throw new Error('"From" bound "' + fromInclusive
+ '" cannot be greater than "until" bound "' + untilInclusive + '".');
const rangeLength = untilInclusive - fromInclusive + 1;
if (uniqueNumbersCount > rangeLength) throw new Error('The length of the range is ' + rangeLength + '=['
+ fromInclusive + '…' + untilInclusive + '] that is smaller than '
+ uniqueNumbersCount + ' (specified count of result numbers).');
if (uniqueNumbersCount === 0) return [];
// 1/3. Create a new "Set" – object that stores unique values of any type, whether primitive values or object references.
// MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
// Support: Google Chrome 38+(2014.10), Firefox 13+, IE 11+
const uniqueDigits = new Set();
// 2/3. Fill with random numbers.
while (uniqueNumbersCount > uniqueDigits.size) {
// Generate and add an random integer in specified range.
const nextRngNmb = Math.floor(Math.random() * rangeLength) + fromInclusive;
uniqueDigits.add(nextRngNmb);
}
// 3/3. Convert "Set" with unique numbers into an array with "Array.from()".
// MDN – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
// Support: Google Chrome 45+ (2015.09+), Firefox 32+, not IE
const resArray = Array.from(uniqueDigits);
return resArray;
}
The benefits of the current implementation:
当前实施的好处:
- Have a basic check of input arguments– you will not get an unexpected output when the range is too small, etc.
- Support the negative range(not only from 0), e. g. randoms from -1000 to 500, etc.
- Expected behavior: the current most popular answer will extend the range (upper bound) on its own if input bounds are too small. An example: get 10000 unique numbers with a specified range from 0 until 10 need to throw an error due to too small range (10-0+1=11 possible unique numbers only). But the current top answer will hiddenly extend the range until 10000.
- 对输入参数进行基本检查——当范围太小时,你不会得到意外的输出等。
- 支持负范围(不仅是从 0),例如从 -1000 到 500 的随机数等。
- 预期行为:如果输入边界太小,当前最流行的答案将自行扩展范围(上限)。一个例子:获取指定范围从 0 到 10 的 10000 个唯一数字由于范围太小需要抛出错误(仅 10-0+1=11 个可能的唯一数字)。但是当前的最高答案会隐藏地将范围扩展到 10000。
回答by Martin Melichar
I think, this is the most human approach (with using break from while loop), I explained it's mechanism in comments.
我认为,这是最人性化的方法(使用来自 while 循环的中断),我在评论中解释了它的机制。
function generateRandomUniqueNumbersArray (limit) {
//we need to store these numbers somewhere
const array = new Array();
//how many times we added a valid number (for if statement later)
let counter = 0;
//we will be generating random numbers until we are satisfied
while (true) {
//create that number
const newRandomNumber = Math.floor(Math.random() * limit);
//if we do not have this number in our array, we will add it
if (!array.includes(newRandomNumber)) {
array.push(newRandomNumber);
counter++;
}
//if we have enought of numbers, we do not need to generate them anymore
if (counter >= limit) {
break;
}
}
//now hand over this stuff
return array;
}
You can of course add different limit (your amount) to the last 'if' statement, if you need less numbers, but be sure, that it is less or equal to the limit of numbers itself - otherwise it will be infinite loop.
如果您需要更少的数字,您当然可以在最后一个 'if' 语句中添加不同的限制(您的数量),但请确保它小于或等于数字本身的限制 - 否则将是无限循环。