我只是想知道在程序开始时只能将随机数生成器播种一次是否足够.我编写使用随机数的函数.我从不在函数中使用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,程序内容生成器,粒子等)以隔离该系统以进行调试和维护.
如果存储种子,您还可以使用非常少的数据重放逻辑(仅需要来自每个帧的增量输入).这不仅可以让您更轻松地调试应用程序,还可以支持为用户提供录制和重放功能.显然,如果您正在创建重放模式,则需要在每次重播会话之前为每个系统提供系统记录的种子.
还有其他系统,如密码学,您可能需要定期建立新种子.您可能希望随着时间的推移使种子过期,或者需要在与客户端应用程序的每次握手时生成新的种子.但是,您可能希望使用加密库,因为它们可能会比您自己推出的东西更强大.
其中的原因有一个随机数发生器(RNG)需要实例化,以便它可以保持其内部状态,在多线程应用程序,这样你不引入非决定当多个线程使用与进程相同的RNG - 全球国家.假设您有两个线程,每个线程处理一个问题的独立部分 - 如果状态(种子)是RNG实例的私有,那么当您使用已知值为每个线程的RNG设定种子时,您可以具有确定性.另一方面,如果RNG将状态保持在全局变量中,则每个线程观察到的随机数序列取决于它们对RNG的调用的中断 - 您现在已经引入了非确定性.
用于在多线程应用程序中分配工作的一种编程模式是线程池.如果在池中执行排队等候工作线程的工作项目需要一个RNG和你想要的执行是确定的,从每次运行,那么你希望每个线程从拉动新的工作项目后,重新播种的RNG队列
这是一个解决这个问题的SO问题:与实例绑定的确定性随机数生成器(与线程无关)
在单线程应用程序中,没有必要重新种子RNG,事实上它是不受欢迎的,因为通过这样做,你可以在它开始重复之前缩短它的周期.例外情况是@MatthewSanders指出的,密码学 - 在这种情况下,你需要最大熵(最小确定性),因为随机数被用作私钥.
| 归档时间: |
|
| 查看次数: |
1406 次 |
| 最近记录: |