C++11 中的随机数:有没有一种简单的方法可以将生成器种子放在代码的一个位置,然后在不同的函数中使用它?

Random numbers in C++11: is there a simple way to seed the generator in one place of the code, then use it in different functions?

本文关键字:位置 一个 代码 然后 函数 一种 简单 有没有 随机数 方法 C++11      更新时间:2023-10-16

在 C++11 之前,我使用了<cstdlib>中的rand(),选择在main()函数中播种(或不播种(生成器非常简单(例如(,然后在 libraryA 中使用由 libraryB 中某处的函数生成的随机数。代码如下所示:

库B(生成随机数,老式方式(:

#include <cstdlib> // rand, RAND_MAX
double GetRandDoubleBetween0And1() {
return ((double)rand()) / ((double)RAND_MAX);
}

主程序:

#include <cstdlib> // srand
#include <ctime> // time, clock
int main() {
bool iWantToSeed = true; // or false,
// decide HERE, applies everywhere!
if(iWantToSeed){
srand((unsigned)time(0) + (unsigned int)clock());
}
// (...)
}

库A(使用来自库 B 的随机数,根据main()中给出的种子生成(:

#include "../folderOfLibraryB/Utils_random.h" // GetRandDoubleBetween0And1
void UseSomeRandomness(){
for(int i = 0; i < 1000000; i++){
double nb = GetRandDoubleBetween0And1();
// (...)
}
}

很简单,对吧?

现在我想使用通过#include <random>提供的 C++11 标准更新GetRandDoubleBetween0And1()。我已经在这里和那里阅读并看到了示例,但我看不出如何使其适应我的三个模块。当然,将发动机播种在GetRandDoubleBetween0And1()内并不是正确的做法......

您是否认为我必须在图书馆 A 中将种子引擎从main()传递到UseSomeRandomness(),然后在图书馆 B 中从UseSomeRandomness()传递到GetRandDoubleBetween0And1()?还是有更简单的方法?

你认为我必须将种子引擎从main((传递到LibraryA中的UseSomeRandomness((,然后从UseSomeRandomness((传递到LibraryB中的GetRandDoubleBetween0And1((吗?

是的。

实例化生成器一次,然后将指向它的引用或指针传递到想要使用它的任何上下文中。

这就像处理任何其他资源一样。

你可以做这样的事情:

#include <random>
inline double GetRandDoubleBetween0And1() {
thread_local static std::mt19937 gen{std::random_device{}()};
thread_local static std::uniform_real_distribution pick{0.0, 1.0};
return pick(gen);
}

inline意味着您可以将其放在头文件中,编译器将仅创建静态对象的一个副本,它将在链接时解析该副本。但是,如果您在动态库中使用它,您将获得不同的副本。在这种情况下,您可以将此函数放在其自己的库中,并将其链接到使用该函数的每个程序。

thread_local确保线程安全(每个线程一个随机生成器(,并且是静态的,它们只初始化一次。

我的"随机"库提供了一个围绕 C++11 个随机类的高度方便的包装器。你可以用一个简单的"get"方法做几乎所有的事情。

对于您的用例,您可以将自动种子random_static包装器与静态 API 一起使用。

例子:

#include "effolkronium/random.hpp"
using Random = effolkronium::random_static;
auto Func( ) { 
return Random::get(-10, 10 )
}
auto Func2( ) { 
return Random::get(-10, 10 )
}
int main( ) {
// Seed static internal engine
Random::seed( MySuperSeed );
}

它是仅单个标头库。

查看github页面: https://github.com/effolkronium/random