我知道如果N不是太大,rand()%N将能够生成介于0和N-1之间的长整数。但是,现在我想从0到N-1生成大约0.1N的整数,是否有一些快速的方法可以做到这一点?
当N很小时,可能会保留一个数组并检查之前是否已生成数字,但随着N的增加,这变得非常慢。而且,如果种子很差,它甚至可能反复产生相同的数字并形成死循环。
另外,我想可以使用散列来分配数字,而开放寻址只是让每个生成的数字都转到下一个空位(例如,如果23生成两次,请尝试23 + 4,23 + 9,23 + 16 ...)但是,对于大型数据化来说,这也很慢。
那么,有没有什么好方法可以在可接受的时间内生成一堆不相交的随机数?谢谢!
P.S.N的大小非常大,至少在10 ^ 6-10 ^ 7的数量级,并且如果它可以在10 ^ 8运行则是最好的。 (实际上问题是N的布尔数组,并随机翻转10%)如果可以实现“改组”算法,它也可以工作。
答案 0 :(得分:3)
经典的解决方案是致电shuffle
;这甚至可以产生0到N-1之间的N个随机数。
如果你担心种子不好,可以从<random>
获得一个不错的RNG,而不是使用旧的那个。
答案 1 :(得分:0)
使用Boost Mersenne Twister来获得更快更好的伪随机数。它使用种子引擎,你不会得到相同的种子(你仍然可能得到两个相同的数字 - 但这是随机性的。)
答案 2 :(得分:0)
Bloom过滤器是实现满足您需求的宽松集语义的一种非常有效的方法。您需要知道的是,如果元素肯定不在集合中,那么您可以将其接受到随机值列表中。
http://en.wikipedia.org/wiki/Bloom_filter
引用维基百科: 查询返回“可能在集合中”或“绝对不在集合中”
随机播放不会做你想要的: http://www.cplusplus.com/reference/algorithm/shuffle/ 具体而言,它不会删除重复的值。
其中一条评论中引用的集合容器可以使用,但您可以在问题中担心所有费用。
答案 3 :(得分:0)
函数srand(-time(NULL));
这会将系统时间称为种子,每次都会生成不同的随机数。在这种情况下种子永远不会穷!并且不要忘记调用相关的Header文件。
答案 4 :(得分:0)
首先,我同意其他评论者关于使用<random>
或Boost Mersenne Twister优先于rand()
。
如果您的真正目标是在数组中翻转大约 10%的位,为什么不直接解决? Mersenne Twister已经可以生成Uniform(0,1)和整数,或者如果你使用<random>
,你可以按RAND_MAX + 1
缩放以转换为Uniform(0,1)。迭代您的位数组,为每个索引生成一个带有Uniform(0,1)分布的值u
,如果u <= 0.1
翻转该位。
如果它必须是10%,那么你的选择是
1)接受/拒绝:随机生成索引,跟踪已经在哈希表中生成的索引,如果得到重复,则再试一次。人们认为这比实际效率低很多。目标为0.1N,最初你几乎不会产生重复,最后它将是大约十分之一,在你获得一个新值之前,尝试10/9或1.11次尝试作为预期的尝试次数。它尝试超过3次或4次的可能性非常小。将其视为获得目标设置的平均开销约为5%(因为实际开销范围从开始时的0到结束时的11%)。
2)改组:你需要创建一个包含10 ^ 7或10 ^ 8值的数组,但好消息是你只需要洗掉10%的值。一旦您置换了前10%,您就可以停止并选择该子集。以更高的存储成本获得良好的运行时效率。