/ 猿问

# 生成（0-X）范围内的唯一编号，并保留历史记录以防止重复

2019-12-06 15:08:29

（可选）完成此操作后（例如，范围已“用尽”），只需返回该范围内的随机数即可。

## 3 回答

qq_花开花谢_0

function makeRandomRange(x) {

var used = new Array(x),

exhausted = false;

return function getRandom() {

var random = Math.floor(Math.random() * x);

if (exhausted) {

return random;

} else {

for (var i=0; i<x; i++) {

random = (random + 1) % x;

if (random in used)

continue;

used[random] = true;

return random;

}

// no free place found

exhausted = true;

used = null; // free memory

return random;

}

};

}

var generate = makeRandomRange(20);

var x1 = generate(),

x2 = generate(),

...

function makeRandomRange(x) {

var range = new Array(x),

pointer = x;

return function getRandom() {

pointer = (pointer-1+x) % x;

var random = Math.floor(Math.random() * pointer);

var num = (random in range) ? range[random] : random;

range[random] = (pointer in range) ? range[pointer] : pointer;

return range[pointer] = num;

};

}

（jsfiddle.net上的演示）

function makeRandomRange(x) {

var range = new Array(x),

pointer = x;

return function getRandom() {

if (range) {

pointer--;

var random = Math.floor(Math.random() * pointer);

var num = (random in range) ? range[random] : random;

range[random] = (pointer in range) ? range[pointer] : pointer;

range[pointer] = num;

if (pointer <= 0) { // first x numbers had been unique

range = null; // free memory;

}

return num;

} else {

return Math.floor(Math.random() * x);

}

};

}

• 如果`N`比更大`M`，您将要使用一种算法，例如Bentley和Floyd在他的专栏“ Programming Pearls：辉煌的示例 ”中建议的算法（此处暂时不带ACM的锁定屏幕而提供），我真的推荐这样做他们明确给出代码并根据哈希表等进行讨论；那里有一些整洁的花样

• 如果`N`与处于同一范围内`M`，则您可能需要使用Fisher-Yates随机播放，但仅需`M`一步即可停止（而不是`N`

• 如果您真的不太了解，那么Devroye关于随机生成的书第647页上的算法非常快。

// Generates a unique number from a range

// keeps track of generated numbers in a history array

// if all numbers in the range have been returned once, keep outputting random numbers within the range

var UniqueRandom = { NumHistory: new Array(), generate: function(maxNum) {

var current = Math.round(Math.random()*(maxNum-1));

if (maxNum > 1 && this.NumHistory.length > 0) {

if (this.NumHistory.length != maxNum) {

while(\$.inArray(current, this.NumHistory) != -1) { current = Math.round(Math.random()*(maxNum-1)); }

this.NumHistory.push(current);

return current;

} else {

//unique numbers done, continue outputting random numbers, or we could reset the history array (NumHistory = [];)

return current;

}

} else {

//first time only

this.NumHistory.push(current);

return current;

}

}

};

• 3 回答
• 0 关注
• 229 浏览

0/150