我知道,如果N不太大,rand() %N将能够在0和N-1之间生成一个长整数。然而,现在我想要生成从0到N1的大约0.1N个整数,有什么快速的方法吗?
当N很小时,可能会保留一个数组,并检查以前是否生成了这个数字,但是随着N的增加,这会变得非常缓慢。而且,如果种子不好,它甚至可能一次又一次地产生相同的数目,形成一个死胡同的循环。
另外,我想可以使用散列来分配数字,而打开寻址只是让每个生成的数字都转到下一个空点(例如,如果23被生成两次,尝试23+4、23+9、23+16.)但对于大规模数据化来说,这也是缓慢的。
那么,有什么好的方法在可接受的时间内生成一串不相交的随机数呢?谢谢!
N的P.S.the大小相当大,至少在10^6-10^7之间,如果它能在10^8运行,则最好。(实际上问题是N的布尔数组,随机翻转其中的10% )如果可以实现“洗牌”算法,它也会工作。
发布于 2014-07-26 16:54:58
首先,我同意其他人关于使用<random>或Boost Mersenne而不是rand()的评论。
如果你真正的目标是翻转数组中大约10%的位,为什么不直接处理呢?Mersenne已经可以生成统一(0,1)和整数,或者,如果您使用<random>,您可以通过RAND_MAX + 1缩放转换为统一(0,1)。迭代您的位数组,为每个索引生成一个具有统一(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%,你可以停止,这子集是你的选择。良好的运行效率和更大的存储成本。
发布于 2014-07-25 23:36:56
经典的解决方案是调用shuffle;这甚至可以在0到N-1之间产生N个随机数。
如果你担心坏种子,可以从<random>获得一个不错的RNG,而不是使用旧的C。
发布于 2014-07-25 23:49:33
首先,使用Boost Mersenne Twister进行更快、更好的伪随机数。它使用种子引擎,您不会得到相同的种子(您仍然可以得到两个相同的数字--但这是随机的)。
https://stackoverflow.com/questions/24965964
复制相似问题