【发布时间】:2014-12-05 07:30:34
【问题描述】:
背景:我在代码中使用rand()、std::rand()、std::random_shuffle()等函数进行科学计算。为了能够重现我的结果,我总是明确指定随机种子,并通过srand() 设置它。直到最近,当我发现 libxml2 也会在第一次使用时懒惰地调用 srand() - 这是在我早期的 srand() 调用之后。
我填写了bug report to libxml2 about its srand() call,但我得到了答案:
然后先初始化 libxml2。 这是从图书馆发出的完全合法的电话。你应该 不要指望没有其他人打电话给
srand(),并且手册页无处可去 声明应避免多次使用srand()
这实际上是我现在的问题。如果一般政策是每个库都可以/应该/将调用srand(),并且我可以/可能还会在这里和那里调用它,我真的不知道这有什么用处。或者rand() 有什么用处?
这就是为什么我认为,一般(不成文的)策略是任何库都不应该调用srand(),并且应用程序应该在开始时只调用一次。 (不考虑多线程。我想在这种情况下,无论如何你应该使用不同的东西。)
我还尝试研究一下哪些其他库实际上调用了srand(),但我没有找到。有吗?
我目前的解决方法是这个丑陋的代码:
{
// On the first call to xmlDictCreate,
// libxml2 will initialize some internal randomize system,
// which calls srand(time(NULL)).
// So, do that first call here now, so that we can use our
// own random seed.
xmlDictPtr p = xmlDictCreate();
xmlDictFree(p);
}
srand(my_own_seed);
可能唯一干净的解决方案是根本不使用它,而只使用我自己的随机生成器(可能通过C++11 <random>)。但这不是真正的问题。 问题是,谁应该打电话给srand(),如果每个人都打电话,那么rand()有什么用呢?
【问题讨论】:
-
如果你可以使用 C++11 库,你应该看看en.cppreference.com/w/cpp/numeric/random
-
IMO 这是你的设计缺陷。当您需要可预测的随机值(addictio in adiectio 本身)时,您永远不应该使用程序的所有其他部分(包括您使用的库)也可能使用的全局随机生成器。即使那些其他部分不调用
srand(),只要调用rand(),它们也会影响全局随机生成器。 -
对不起,出于安全原因使用 srand/rand,正如 libxml2 家伙声称的那样,是可笑的。
-
修改全局状态的库(包括调用
srand())已损坏。他们的回答只是胡扯,试图为不合理的事情辩护。其余的:如果您需要可重复的随机数进行科学计算,rand()不会满足您的要求。游戏很好,或者只是玩玩,但仅此而已。否则,在 C++11 之前的版本中,您实现自己的,而在 C++11 中,您使用<random>。 (但这并不能让库实现者摆脱困境。) -
@JamesKanze “修改全局状态的库(包括调用 srand())已损坏。” -- 调用 rand 修改全局状态,就像 srand 一样。被破坏的是这些函数具有全局状态。