我应该多久用C++重新编程?

xin*_*_yu 10 c++ c++11

我只是想知道在程序开始时只能将随机数生成器播种一次是否足够.我编写使用随机数的函数.我从不在函数中使用rand()生成器,而是在主条目上调用srand().例如,我的程序可能如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

但是,我注意到在C++ 11的新随机效用集中,随机数生成器必须在使用之前进行实例化.(例如default_random_engine).每次发电机必须单独播种.我想知道是否真的鼓励在需要新发电机时重新安装发电机.我知道我可以像以前一样创建一个全局随机生成器并只播种一次,但我真的不喜欢使用全局变量的想法.否则,如果我创建一个本地随机数生成器,我就会失去全局关闭种子进行调试或其他目的的能力.

我很高兴能够学习C++ 11中的新功能,但有时它会让人感到非常困惑.如果我对新的随机发生器有任何问题,有人能告诉我吗?或者什么可能是C++ 11中的最佳实践?

Mat*_*ers 17

这肯定取决于您正在开发的系统的总体目标,但通常您只需要在初始化该系统时为任何需要随机数生成器(RNG)的系统播种.

在游戏开发中,通常每个系统具有单独的RNG(AI,程序内容生成器,粒子等)以隔离该系统以进行调试和维护.

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

还有其他系统,如密码学,您可能需要定期建立新种子.您可能希望随着时间的推移使种子过期,或者需要在与客户端应用程序的每次握手时生成新的种子.但是,您可能希望使用加密库,因为它们可能会比您自己推出的东西更强大.


amd*_*mdn 7

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

用于在多线程应用程序中分配工作的一种编程模式是线程池.如果在池中执行排队等候工作线程的工作项目需要一个RNG和你想要的执行是确定的,从每次运行,那么你希望每个线程从拉动新的工作项目后,重新播种的RNG队列

  • 这可以作为工作项初始化的一部分来完成
  • 种子可能涉及作业参数的哈希函数
  • 如果你小心这是如何编码的,你可以有伪随机性和确定性,无论工作线程的数量或它们从队列中拉出作业的顺序如何.

这是一个解决这个问题的SO问题:与实例绑定的确定性随机数生成器(与线程无关)

在单线程应用程序中,没有必要重新种子RNG,事实上它是不受欢迎的,因为通过这样做,你可以在它开始重复之前缩短它的周期.例外情况是@MatthewSanders指出的,密码学 - 在这种情况下,你需要最大熵(最小确定性),因为随机数被用作私钥.