Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中生成多个不同的随机数+/C_C++_Random_Hash - Fatal编程技术网

C++ 在C+中生成多个不同的随机数+/C

C++ 在C+中生成多个不同的随机数+/C,c++,random,hash,C++,Random,Hash,我知道如果N不是太大,rand()%N将能够生成一个介于0和N-1之间的长整数。然而,现在我想从0到N-1生成大约0.1N个整数,有什么快速的方法吗 当N很小时,可能会保留一个数组并检查该数字之前是否已生成,但随着N的增加,这将变得非常缓慢。此外,如果种子不好,它甚至可能一次又一次地产生相同的数目,形成一个死循环 另外,我想可以使用散列来分配数字,而开放寻址只是简单地使每个生成的数字转到下一个空位置(例如,如果23生成了两次,请尝试23+4、23+9、23+16…),但这对于大数据量来说也很慢

我知道如果N不是太大,rand()%N将能够生成一个介于0和N-1之间的长整数。然而,现在我想从0到N-1生成大约0.1N个整数,有什么快速的方法吗

当N很小时,可能会保留一个数组并检查该数字之前是否已生成,但随着N的增加,这将变得非常缓慢。此外,如果种子不好,它甚至可能一次又一次地产生相同的数目,形成一个死循环

另外,我想可以使用散列来分配数字,而开放寻址只是简单地使每个生成的数字转到下一个空位置(例如,如果23生成了两次,请尝试23+4、23+9、23+16…),但这对于大数据量来说也很慢

那么,有没有什么好方法可以在可接受的时间内生成一组不相交的随机数呢?谢谢大家!


另外,N的大小相当大,至少在10^6-10^7的数量级,如果它能在10^8的速度下运行最好。(实际上问题是一个N的布尔数组,随机翻转10%)如果可以实现“洗牌”算法,它也会工作。

经典的解决方案是调用
洗牌
;这甚至可以产生0到N-1之间的N个随机数


如果您担心坏种子,请从
获得一个合适的RNG,而不是使用旧的C。开始使用更快更好的伪随机数。它使用一个种子引擎,你不会得到相同的种子(你仍然可能得到两个相同的数字,但这是随机的)。

Bloom过滤器是一种非常有效的方法,可以实现满足你需要的宽松集语义。您需要知道的是,如果某个元素肯定不在集合中,那么您可以将其接受到随机值列表中

引用维基百科: 查询返回“可能在集合中”或“绝对不在集合中”

洗牌不会执行您想要的操作: 具体而言,它不会删除重复的值

在其中一条注释中引用的set容器可以工作,但它具有您在问题中担心的所有成本。

srand(-time(NULL))


这将调用系统时间作为种子,每次生成不同的随机数。在这种情况下,种子永远不会贫瘠!不要忘记调用相对的头文件。

首先,我同意其他评论者关于使用
或Boost Mersenne twitter,而不是使用
rand()


如果您的真正目标是翻转阵列中大约10%的位,那么为什么不直接解决这个问题呢?Mersenne Twister已经可以生成均匀(0,1)和整数,或者,如果使用
,则可以通过
RAND_MAX+1
进行缩放,以转换为均匀(0,1)。迭代你的位数组,为每个索引生成一个均匀(0,1)分布的值
u
,如果
u首先,使用
而不是
rand()
。其次,您可以插入到
std::set
中检查重复项。
rand()%N
非常糟糕。不要使用它。你可能想检查一下C++的标准是什么。至少在N位中量化N的数量级,否则解决方案可能会比另一个更好。生成一个值为0..N-1(或任何需要的范围)的数组,然后将其洗牌。这确保每个值只存在一次,并且顺序是随机的。接受/拒绝实际上运行得很好!事实上,在过去的几天里,我正是使用这种方法来编写程序的,它只需几秒钟就可以运行。虽然对于rand(),它很有可能一次又一次地生成相同的数字(我想这是因为周期很小),但是对于mt19937(),它是非常好的。但是关于洗牌,只存储10^8个0和1的数组(表示“已选择/未关闭”),而不是10^8个长整数,存储效率会更高。然后只需将0的前10%翻转为1,然后排列整个数组。但有什么有效的方法可以做到这一点吗?我的意思是洗牌一个非常大的数组…@MikeWong检查第二个变体。如果从0循环到
k-1
而不是
n-1
,则第一个
k
元素现在包含索引集中任何位置的索引。数组必须具有所有可能的索引,以便每个索引都有机会位于子集中,但您只需对所需数量的元素执行交换。洗牌是有效的,洗牌n项是O(n)。谢谢!我刚刚查看了wiki页面,事实上Fisher-Yates shuffling非常简洁,只有O(n)。还有,Fisher Yates的改组有内置的C++函数吗?(因为即使MelShanne Twitter也包含在C++包中,这也可能吗?)简单地调用SUffFLUE()是否有效?<代码> RAND()>代码>只为特定数量的调用生成一个不同的随机数,以调用代码< > RAND()/<代码>,称为句号。(我认为POSIX要求>=2^31,这对这一点很好,但在非POSIX系统上这可能是一个问题),
RAND_MAX
只能保证至少为32767,因此可能不会直接用于1e7..1e8元素,即使RAND_MAX恰好大于此值,在使用N进行“%”-ing之后,仍然会出现“冲突”所以这必须以某种方式处理。这与我的答案有什么关系?你声称“每次都会生成不同的随机数”,所以我指出,对于特定数量的兰德()呼叫,这是正确的,而在最坏情况下的实现中,具体数字只有32768。这与IMHO非常直接相关。同样重要的是,问题需要得到~1e8个不同的数字,RAND_MAX可能要少得多,而且您还没有解释如何处理这种差异。另外,srand采用了一个未签名的参数,“种子永远不会差”这不是真的-人们在同一秒运行程序,发现他们是g