在我的一个项目中,我遇到需要在给定范围内生成一组数字:
详尽无遗,这意味着它将覆盖给定的大部分内容 范围没有任何重复。
它将保证确定性(每次序列都是 相同)。这可以用固定的种子来实现。
它将是随机的(我对随机数理论不是很精通,但我想有一堆描述随机性的规则。从0,1,2..N这个角度来看,它不是随机的)
我所说的范围可以是整数范围,也可以是实数范围。
例如,如果我使用标准C#随机生成器在范围[0,9]中生成10个数字,我会得到这个:
0 0 1 2 0 1 5 6 2 6
正如你所看到的,给定范围的很大一部分仍然是“未开发的”并且有很多重复。
当然,输入空间可能非常大,因此记住以前选择的值不是一种选择。
解决这个问题的正确方法是什么?
感谢。
评论后: 好吧我同意随机不是正确的词,但我希望你明白我想要实现的目标。我想探索可能很大的给定范围,因此在内存列表中不是一个选项。如果范围是(0,10)并且我想要三个数字我想保证那些数字将是不同的并且它们将“描述范围”(即它们不会都在下半部分等)。
确定性部分意味着我想使用标准rng和固定种子之类的东西,所以我可以完全控制序列。
我希望我让事情更清楚一点。
感谢。
答案 0 :(得分:4)
以下是三种不同权衡的选择:
答案 1 :(得分:3)
如果你只是需要什么,那么这样的事情呢?
maxint = 16
step = 7
sequence = 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, 0
如果选择右步,它将在重复之前生成整个间隔。您可以使用不同的步骤值来获得“看起来”不错的东西。这里的“种子”是你从序列开始的地方。
这是随机的吗?当然不是。根据随机性的统计检验,它看起来是随机的吗?这可能取决于步骤,但可能这看起来根本不是统计随机的。但是,它肯定会选择范围内的数字,而不是原始顺序,并且没有记录到目前为止所选择的数字。
事实上,你可以通过列出一些因素来使这看起来更好 - 如[1,2,3,4,5],[6,7,8,9,10],[11,12, 13,14,15,16] - 并使用它们的混洗版本来计算step * factor(mod maxint)。假设我们改变了[3,2,4,5,1],[6,8,9,10,7],[13,16,12,11,14,15]等示例因子列表。然后我们得到序列
5, 14, 12, 3, 7, 10, 8, 15, 6, 1, 11, 0, 4, 13, 2, 9
因子列表的大小是完全可调的,因此您可以根据需要存储尽可能多的内存。更大的因子列表,更随机性。无论因素列表大小如何都不重复。当你耗尽一个因子列表时,生成一个新因子就像计算和改组一样容易。
答案 2 :(得分:1)
我的印象是,您所寻找的是一个随机排序的数字列表,而不是随机的数字列表。您应该能够使用以下伪代码获得此功能。更好的数学可能会告诉我这实际上是不是随机的:
list = [ 1 .. 100 ]
for item,index in list:
location = random_integer_below(list.length - index)
list.switch(index,location+index)
基本上,浏览列表并从列表的其余部分中选择一个随机项,以便在您所在的位置使用。这应该随机排列列表中的项目。如果你需要每次都重现相同的随机顺序,可以考虑保存数组,或者确保random_integer_below总是以给定种子的相同顺序返回数字。
答案 3 :(得分:0)
不使用随机数生成器来选择范围内的数字。最终会发生的是你还有一个数字要填充,你的随机数发生器会反复循环,直到它选择那个数字。根据随机数生成器,无法保证将会发生。
您应该做的是生成所需范围内的数字列表,然后使用随机数生成器对列表进行随机播放。 shuffle被称为Fisher-Yates shuffle,或者有时被称为Knuth shuffle。这是伪代码,用于将n个元素的数组x混洗,索引从0到 n -1:
从 n -1到1的 i
j =随机整数,使得0≤ j ≤ i
交换 x [ i ]和 x [ j ]
答案 4 :(得分:0)
按顺序生成包含范围的数组。所以数组包含[0, 1, 2, 3, 4, 5, ... N]
。然后使用Fisher-Yates Shuffle来加扰数组。然后,您可以遍历数组以获取随机数。
如果您需要重复性,请在随机播放开始时使用相同的值为随机数生成器播种。