如何确保随机数是唯一的而不是重复的?

我有一个生成随机数的简单代码

SecureRandom random = new SecureRandom(); ... public int getRandomNumber(int maxValue) { return random.nextInt(maxValue); } 

上面的方法大约被调用10次(不是循环)。 我想确保所有数字都是唯一的(假设maxValue > 1000 )。

我可以确定每次打电话都会得到唯一的号码吗? 如果没有,我该如何解决?

编辑:我可能含糊地说。 我想避免手动检查,如果我真的有唯一的数字,所以我想知道是否有更好的解决方案。

有不同的方法来实现这一点,哪个更合适将取决于您需要从多少数量中选择的数量。

  • 如果您从大量潜在数字中选择少量随机数,那么您最好只将先前选择的数字存储在一个集合中,并“手动”检查重复数字。 大多数情况下,您实际上不会获得重复,并且实际上测试的成本几乎为零。 听起来可能不那么优雅,但实际上并不像听起来那么糟糕。
  • 一些基础随机数生成算法不会在其“原始”级别产生重复。 因此,例如,称为XORShift生成器的算法可以有效地生成特定范围内的所有数字,无需重复就可以进行混洗。 所以你基本上在序列中选择一个随机的起始点然后只生成下面的n个数字,你知道不会有重复。 但是在这种情况下你不能随意选择“max”:它必须是所讨论的发生器的自然最大值。
  • 如果可能数字的范围很小,但您需要选择的数字的数量在该范围的几个数量级内,那么您可以将其视为随机选择问题。 例如,要选择10,000,000范围内的100,000个数字而不重复,我可以这样做:

    设m是到目前为止我选择的随机数的数量

    对于i = 1到10,000,000

    生成0-1范围内的随机(浮点)数r

    如果(r <(100,000-m)/(10,000,000-i)),则将i添加到列表中并递增m

    随机播放列表,然后根据需要从列表中依次选择数字

但显然,如果你需要选择一些相当大比例的数字,那么选择后一种选择只有很多意义。 为了选择1到10亿范围内的10个数字,你将产生10亿个随机数,当你只是检查重复数据时,你实际上不太可能得到重复,并且最终只会生成10个随机数数字。

随机序列并不意味着所有值都是唯一的。 序列1,1,1,1与序列712,4,22,424完全一样。

换句话说,如果您想要保证一系列唯一数字,一次生成10个,检查您选择的唯一性条件并存储它们,然后从该列表中选择一个数字,而不是在您的列表中生成一个随机数10个地方。

每次调用Random#nextInt(int)你都会得到

伪随机,在0(包括)和指定值(不包括)之间均匀分布的int值。

如果你想要x唯一的数字,不断获得新的数字,直到你有这么多,然后从该列表中选择你的“随机”数字。 但是,由于您正在过滤生成的数字,因此它们将不再是真正的随机数。

对于如此少量的可能值,一个简单的实现是将1000个整数放在一个列表中,并且有一个循环,在每次迭代时,生成一个介于0和list.size()之间的随机数,选择存储的数字在此索引处,将其从列表中删除。

这是代码,CPU以内存为代价非常高效。 每个potiental值cost sizeof(int) * maxValue 。 无符号整数最多可以达到65535。 对于1000位16位整数值,可以以大量内存2000字节为代价使用long。

数组的整个目的是说你之前是否使用过这个值1 = yes else = no’while循环将继续生成随机数,直到找到唯一值。 ‘找到一个好的随机值后,它会将其标记为已使用,然后返回它。 ‘注意变量a的范围,好像它超出了你的数组可以擦除的范围。 ‘我在c中使用过它并且它有效。 ‘可能需要花点时间才能让它在Java中运行。

 unsigned int a(1000); public int getRandomNumber(int maxValue) { unsigned int rand; while(a(rand)==1) { rand=random.nextInt(maxValue); if (a(rand)!=1) { a(rand)=1; return rand;} } }