4

所以,每次我开发一些大的东西时,多个模块组合在一起构建最终功能时,我一直在想同一个问题:如果超过 1 个模块需要使用随机函数,在哪里初始化随机种子?

如果我有某个需要随机的类(例如,通过使用自我实现的快速排序对输入数组进行排序来初始化自身的类,所以我需要一个随机的枢轴选择),我通常有一个私有static bool isRandOn;变量,所以在我开始之前随机枢轴选择,我检查该变量并srand(time(NULL));在随机尚未打开时执行。

如果我在命名空间中有大量实用程序函数,我会做类似的事情:我将这样一个变量放在我的 utils 库中的匿名命名空间中,并与类做或多或少相同的事情。

我遇到的问题是在组合这些模块时。就其本身而言,我知道每个模块不会多次设置种子。但是,我希望能够一起使用不同数量的模块,我希望其他人能够独立于其他人使用我的一个或多个模块......

那么,处理多个需要随机种子的模块的最佳方法是什么?在每个模块中设置种子?根本不设置种子,而是记录随机的用法并让用户在他想使用模块时初始化种子?第三点?

4

4 回答 4

2

我建议使用 Boost.Random 而不是依赖在程序级别共享的一些全局状态。

Boost.Random 有两个概念:

  • 引擎:生成随机数
  • 分布:调整引擎的结果以提供适合特定分布(正态、泊松、高斯......)的结果

然后,每个模块可能有自己的引擎,或者实际上是其中的几个:没有特定理由让给定引擎在同一模块内的几个不同功能之间共享。

最后一句话:无论您做什么,请确保您有一种方法可以确定地设置种子以用于错误重现目的。错误重现可能会受益于拥有多个引擎(部件的隔离有帮助)。

于 2012-05-25T09:12:30.640 回答
1

您可以为随机数生成创建一个特殊的“模块”,并从应用程序的其他部分使用它。然后,您只需在初始化随机数模块时播种一次。

于 2012-05-25T09:07:29.787 回答
0

@penelope 给出了正确答案。后面有一些生成伪随机数序列的复杂算法rand()。这就像一些函数rand_func(prev_rand),它从前一个生成下一个伪随机数。您第一次调用srand(time(NULL)),在这些术语中设置prev_rand为 假设time(NULL)是非常不确定的。因此,您可以安全地srand()多次调用 (which sets )。

特殊问题是您是否需要可预测的伪随机序列:例如,srand(0)等等。但这似乎不是您的情况。

于 2012-05-25T09:29:22.540 回答
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());

这样,您可以确保:

  1. 您将至少在第一次通过时初始化您的 PRNG;

  2. 您永远不会在模块内多次重新初始化随机序列。

希望这有帮助!

于 2018-08-23T14:51:04.923 回答