我想在一个范围内得到一个随机数,不包括一个数字(例如从1到1000不包括577)。我搜索了一个解决方案,但从未解决过我的问题。
我想要类似的东西:
Math.floor((Math.random() * 1000) + 1).exclude(577);
我想避免for
循环尽可能多地创建数组,因为长度总是不同的(有时是1到10000,有时是685到888555444等),生成它的过程可能需要太多时间了。
我已经尝试过:
Javascript - Generating Random numbers in a Range, excluding certain numbers
How can I generate a random number within a range but exclude some?
我怎么能实现这个目标?
答案 0 :(得分:21)
获取某个范围[a, b]
中的随机整数的最快方法是在c
和a
之间生成它,不包括一个值b-1
{1}},如果它高于或等于c
,则将其递增1。
这是一个有效的功能:
function randomExcluded(min, max, excluded) {
var n = Math.floor(Math.random() * (max-min) + min);
if (n >= excluded) n++;
return n;
}
此解决方案只有complexity的O(1)。
答案 1 :(得分:3)
一种可能性是不添加1,如果该数字出来,则指定最后一个可能的值。
例如:
var result = Math.floor((Math.random() * 100000));
if(result==577) result = 100000;
通过这种方式,您不需要重新启动随机方法,但会重复。并且符合随机的目标。
答案 2 :(得分:2)
正如@ebyrob建议的那样,你可以创建一个函数,通过为每个大于或等于的值加1,从较小的集到具有排除值的较大集进行映射:
// min - integer
// max - integer
// exclusions - array of integers
// - must contain unique integers between min & max
function RandomNumber(min, max, exclusions) {
// As @Fabian pointed out, sorting is necessary
// We use concat to avoid mutating the original array
// See: http://stackoverflow.com/questions/9592740/how-can-you-sort-an-array-without-mutating-the-original-array
var exclusionsSorted = exclusions.concat().sort(function(a, b) {
return a - b
});
var logicalMax = max - exclusionsSorted.length;
var randomNumber = Math.floor(Math.random() * (logicalMax - min + 1)) + min;
for(var i = 0; i < exclusionsSorted.length; i++) {
if (randomNumber >= exclusionsSorted[i]) {
randomNumber++;
}
}
return randomNumber;
}
另外,我认为@ JesusCuesta的回答提供a simpler mapping并且更好。
更新:我原来的回答中有许多问题。
答案 3 :(得分:1)
您可以继续生成该号码,直到您发现它符合您的需求为止:
function randomExcluded(start, end, excluded) {
var n = excluded
while (n == excluded)
n = Math.floor((Math.random() * (end-start+1) + start));
return n;
}
myRandom = randomExcluded(1, 10000, 577);
顺便说一下,这不是最好的解决方案,请查看my other answer以获得更好的解决方案!
答案 4 :(得分:1)
扩展@Jesus Cuesta的回答:
function RandomNumber(min, max, exclusions) {
var hash = new Object();
for(var i = 0; i < exclusions.length; ++i ) { // TODO: run only once as setup
hash[exclusions[i]] = i + max - exclusions.length;
}
var randomNumber = Math.floor((Math.random() * (max - min - exclusions.length)) + min);
if (hash.hasOwnProperty(randomNumber)) {
randomNumber = hash[randomNumber];
}
return randomNumber;
}
注意:这仅适用于max - exclusions.length&gt;最大限度的排除。很近。
答案 5 :(得分:0)
因此,我们的想法是再次调用该函数,具体取决于您要排除的值。
所以看看这个例子
function generateRandom(min, max,valuetoexclude) {
var num = Math.floor(Math.random() * (max - min + 1)) + min;
return (num === valuetoexclude) ? generateRandom(min, max) : num;
}
var test = generateRandom(1, 10000,577)
答案 6 :(得分:0)
生成随机数,如果匹配排除的数字,则添加另一个随机数(-20到20)
var max = 99999, min = 1, exclude = 577;
var num = Math.floor(Math.random() * (max - min)) + min ;
while(num == exclude || num > max || num < min ) {
var rand = Math.random() > .5 ? -20 : 20 ;
num += Math.floor((Math.random() * (rand));
}
答案 7 :(得分:-2)
从计算中排除数字:
function toggleRand() {
// demonstration code only.
// this algorithm does NOT produce random numbers.
// return `0` - `576` , `578` - `n`
return [Math.floor((Math.random() * 576) + 1)
,Math.floor(Math.random() * (100000 - 578) + 1)
]
// select "random" index
[Math.random() > .5 ? 0 : 1];
}
console.log(toggleRand());
&#13;
或者,使用String.prototype.replace()
与RegExp
/^(577)$/
匹配应从结果中排除的数字;使用[0-99]
,new Date().getTime()
和isNaN()
String.prototype.slice()
中的其他随机数
console.log(
+String(Math.floor(Math.random()*(578 - 575) + 575))
.replace(/^(577)$/,String(isNaN("$1")&&new Date().getTime()).slice(-2))
);
&#13;
还可以使用String.prototype.match()
来过滤结果:
console.log(
+String(Math.floor(Math.random()*10))
.replace(/^(5)$/,String(isNaN("$1")&&new Date().getTime()).match(/[^5]/g).slice(-1)[0])
);
&#13;