JavaScript随机数生成:空间10 ^ 6中唯一的500个整数:碰撞

时间:2018-12-13 21:08:48

标签: javascript random

下面是JS中随机整数生成的一个非常简单的示例,其中我丝毫不“拉伸极限”。

我只能从10 ^ 6很大的空间中生成500个唯一的随机整数。

但是,如果您继续单击该按钮,则偶尔会在500个中看到499或498个唯一的按钮。它的发生频率不是很高,但是可能每单击10或15次就会发生一次。这是为什么?我的空间是一百万。我不希望在第10次或第20次点击的频率下发生500次采样的碰撞。

要进行测试,请继续单击按钮并观看控制台

function run() {
  var nums = new Set();

  for (var i = 0; i < 500; i++) {
    nums.add(randomInteger10to6th());
  }

  console.clear();
  console.log('Random 10^6 Unique Integer set: ' + nums.size);
}

function randomInteger10to6th() {
   return Math.round(Math.random() * Math.pow(10,6))
}
<button id="run" onclick="run();">Run 500 Random Integers, Space: 10^6</button>

4 个答案:

答案 0 :(得分:9)

当您从1-1e6中选择500个随机数时,看到所有唯一数字的概率可以计算如下: 1e6 / 1e6 * 999,999 / 1e6 * 999,998 / 1e6 * ... * 999,501 / 1e6

这大约是0.88

这意味着超过10%的时间,您将在500个随机变量的列表中至少有一个重复项。

您可以在下面的代码段中对100个实验进行验证:

function run() {
  var nums = new Set();
  for (var i = 0; i < 500; i++) {
    nums.add(randomInteger10to6th());
  }
  return nums;
}

function randomInteger10to6th() {
  return Math.round(Math.random() * Math.pow(10, 6))
}

// perform 100 experiments and see how many have duplicates
var uniques = 0, collisions = 0;
for (var i = 0; i < 100; i++) {
  var nums = run();
  if (nums.size === 500) uniques++;
  else collisions++;
}

console.log('Runs that generated unique numbers', uniques);
console.log('Runs that resulted in collisions', collisions);

答案 1 :(得分:1)

“随机”仅表示:它是随机的。不管之前选择了什么,范围内的每个值都具有相同的被选择概率。因此,即使选择了数字5,它仍然有再次选择5的机会与选择任何其他数字的机会相同。您不应该期望随机数会避免重复-如果重复的话,它们就不会是随机的:)

答案 2 :(得分:1)

由于您要从大量样本中生成相对较少的随机数,因此您应该能够在碰撞时重新生成新数。添加随机数直到达到500,都会导致对随机数生成器的一些额外调用,但这将保证500个唯一数字:

function run() {
    var nums = new Set();
  
    while (nums.size < 500){
       nums.add(randomInteger10to6th());
     }
  
    console.clear();
    console.log('Random 10^6 Unique Integer set: ' + nums.size);
  }
  
function randomInteger10to6th() {
   return Math.round(Math.random() * Math.pow(10,6))
}
<button id="run" onclick="run();">Run 500 Random Integers, Space: 10^6</button>

答案 3 :(得分:0)

您也可以使用简单数组代替Set()。首先,创建包含500个索引的数组,然后填充它。

function run() {
      /* first create an array with 500 slots, then fill it with 
         undefined ( fill() without args is undefined ). For the 
         last step map through 500 slots of undefined and overwrite 
         it with a random number */
      return new Array(500).fill().map(x => Math.round(Math.random() * Math.pow(10,6)))
}

console.log(run().length)
<button id="run" onclick="run();">Run 500 Random Integers, Space: 10^6</button>

如果您想删除重复项,则只需将它们过滤掉即可重新计算。

function run() {
  // same like the upper function but with a duplicates filter
  let arrayWithNumbers = new Array(500).fill().map(x => Math.round(Math.random() * Math.pow(10,6))).filter((item, idx, self) => self.indexOf(item) == idx)
  // run again if array less than 500
  if(arrayWithNumbers.length !== 500) { 
   run() 
  }

  return arrayWithNumbers
}

console.log(run().length)
<button id="run" onclick="run();">Run 500 Random Integers, Space: 10^6</button>