# 在范围（0 – X）内生成唯一编号，保留历史logging以防止重复

• 如果`N``M`大得多，那么你需要使用Bentley和Floyd在他的专栏“ 编程珍珠：一个辉煌的样本 ”（这里暂时没有ACM的locking屏幕）中build议的algorithm，我真的推荐这是因为他们明确地给出了代码和散列表等方面的讨论。 那里有几个巧妙的技巧

• 如果`N``M`处于相同的范围内，那么您可能想要使用Fisher-Yates shuffle，但仅在`M`步之后停止（而不是`N`

• 如果你真的不知道那么Devroye关于随机生成的书的第647页的algorithm是相当快的 。

` `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); } }; }` `

（ 演示 ）

` `// 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; } } };` `