所以,每次我开发一些大的东西,多个模块聚集在一起构建最终功能时,我一直想知道同样的问题:如果多于1个模块需要使用随机函数,那么初始化随机种子的位置?
如果我有一个需要随机的类(例如,通过使用自我实现的快速排序对输入数组进行排序来初始化自己的类,那么我需要随机选择一个),我通常有一个私有{{1}变量,所以在我开始随机数据库选择之前,我检查该变量并且如果随机数尚未开启则执行static bool isRandOn;
。
如果我在命名空间中有大量的实用程序函数,我会做一个非常类似的事情:我将这样一个变量放在我的utils库中的匿名命名空间中,并且和类一样执行或多或少的相同操作
我遇到的问题是组合这些模块的时候。总而言之,我知道每个模块都不会多次设置种子。但是,我希望能够将各种模块一起使用,我希望其他人能够独立于其他人使用我的一个或多个模块......
那么,处理多个随机种子需求模块的最佳方式是什么?在每个模块中设置种子?根本不设置种子,而是记录随机的使用并让用户初始化种子,如果他想使用该模块?第三个什么?
答案 0 :(得分:2)
我建议使用Boost.Random,而不是依赖于在程序级别共享的某个全局状态。
Boost.Random有两个概念:
每个模块可能拥有自己的引擎,或者实际上有几个引擎:没有特定的原因可以在同一模块中的多个不同功能之间共享给定的引擎。
最后一句话:无论你做什么,都要确保你有办法确定性地设置种子用于bug repro目的。 Bug repro可能会受益于多个引擎(隔离部件有帮助)。
答案 1 :(得分:1)
您可以为随机数生成一个特殊的“模块”,并使用应用程序其他部分的模块。然后在初始化随机数模块时只播种一次。
答案 2 :(得分:0)
@penelope给出了正确答案。存在一些用于在rand()
后面生成伪随机数序列的复杂算法。这就像某个函数rand_func(prev_rand)
,它从前一个生成下一个伪随机数。您第一次拨打srand(time(NULL))
,其中prev_rand
设置为time(NULL)
,假设srand()
未完全确定。因此,您可以安全地多次调用srand(0)
(设置)。
特殊问题是,如果你需要可预测的伪随机序列:例如,{{1}}等等。但似乎不是你的情况。
答案 3 :(得分:0)
避免重复总是相同的初始随机序列的最佳方法是在调用random()
函数的每个模块中执行以下操作:
/* Global variable to remember if we already initialized the PRNG */
static bool seed_initialized = false;
/* Helper function to avoid having always the same sequence again and again */
static void
prng_init (unsigned int seed)
{
if (!seed_initialized)
{
srandom (seed);
seed_initialized = true;
}
}
而且,每次在函数中使用random()
时,都将使用类似以下内容的函数来启动该函数:
/* Initializing PRNG with a 'reasonably strong' random seed for our purpose */
prng_init (time (NULL) - getpid());
这样,您可以确保:
您将至少在第一次使用时初始化PRNG;
您将永远不会在模块内多次重复初始化随机序列。
希望获得帮助!