2013-03-03 43 views
9

我只是想知道是否足够在程序开始时只播放一次随机数发生器。我编写使用随机数的函数。我从来没有在函数内生成rand()生成器,而是在main条目中保留调用srand()。例如。我的程序可能看起来像:我应该多久使用一次C++?

void func1() 
{ 
    std::cout << "This is func1 " << std::rand() << std::endl; 
} 

void func2() 
{ 
    std::cout << "This is func2 " << std::rand() << std::endl; 
} 

int main() 
{ 
    std::srand(std::time(NULL)); 
    func1(); 
    func2(); 
    return 0; 
} 

通过这样做,我可以很容易地从主入口关闭播种。它在调试程序时非常有用 - 每次我在没有播种的情况下运行程序时,结果都保持不变。有时,如果由于某个随机数而出现问题,如果要生成一组不同的随机数,它可能会消失,所以我更喜欢这样一种简单的机制来关闭播种。

不过,我注意到在C++ 11的新的随机工具一套,随机数发生器使用前被实例化。 (例如,default_random_engine)。每次发电机必须分开播种。我想知道是否实际上鼓励在需要新发电机的时候重新安装发电机。我知道我可以创建一个全局随机生成器,并像以前一样只播种一次,但我根本不喜欢使用全局变量的想法。否则,如果我创建一个本地随机数生成器,我有点失去全局关闭种子以进行调试或其他目的的能力。

我很高兴能够学习C++ 11中的新功能,但有时候这很让人困惑。任何人都可以让我知道,如果我有新的随机发生器有什么问题吗?或者什么可能是C++ 11的最佳实践?

+0

有一个全局种子函数,它返回当前时间或(在调试模式下)一个常量。 – 2013-03-03 06:44:51

回答

7

的原因之一,对于具有随机数发生器(RNG)需要实例化,以便它可以保持其内部状态,这样,在多线程应用程序,你不引入非决定当多个线程使用与过程全局状态相同的RNG。假设你有两个线程,每个线程处理一个问题的独立部分 - 如果状态(种子)对RNG实例是私有的,那么当你为每个线程的RNG赋一个已知值时,你可以有确定性。另一方面,如果RNG在全局变量中保持状态,则每个线程观察到的随机数序列取决于它们对RNG调用的中断 - 现在您已经引入了非确定性。是,用于在多线程应用程序分配工作

一个编程模式是一个thread pool。如果排队等待池中的工作线程执行的工作项需要一个RNG,并且您希望执行从运行到确定运行,那么您希望每个线程在从工作线中拉出一个新工作项后重新生成RNG队列

  • 这是可以做到的初始化工作项目的一部分
  • 种子可能涉及的参数hash function作业
  • ,如果你仔细考虑这点是如何编码你可以有假 - 随机性 和确定性,无论工作线程的数量或他们将作业从队列中取出的顺序如何。

下面是一个SO问题与此交易:Deterministic random number generator tied to instance (thread independent)

在单线程应用程序无需重新播种的RNG,而事实上这是不可取的,因为这样做,你缩短它的在它开始重复之前循环。这是一个例外@MatthewSanders指出,密码 - 在这种情况下,你需要最大熵(最小确定性),因为随机数被用作私钥。

+1

非常感谢!看来我一直在使用单线程应用程序太久。现在我相信我会为多线程应用程序单独保留随机数生成器。 – 2013-03-03 12:29:57

17

这肯定会取决于您正在开发的系统的总体目标,但一般而言,您只需要种子,需要一个随机数发生器(RNG)曾在该系统的初始化任何系统。

在游戏开发中,通常具有每个系统一个单独的RNG(AI,程序内容发生器,颗粒等)到该系统隔离用于调试和维护。

如果存储的种子还可以重放用很少的数据(只从每帧需要增量输入)的逻辑。这不仅可以让您更轻松地调试应用程序,还可以让您支持用户的录制和重播功能。显然,如果您创建重放模式,系统需要在每个重播会话之前为每个系统提供记录的种子。

还有其他一些系统,如密码术,您可能想要定期建立一个新的种子。您可能希望随时间推移种子,或者需要与客户端应用程序握手时生成新的种子。然而,你可能会想要使用一个加密库,因为它们可能会比你自己推出的东西更加强大。

+1

真棒答案,非常全面。 +1 – 2013-03-03 06:50:19

+0

非常感谢!我学到了很多。 – 2013-03-03 12:31:33

相关问题