我有以下代码:
Class B {
void generator()
{
// creating random number generator
boost::mt19937 randgen(static_cast<unsigned int>(std::time(0)));
boost::normal_distribution<float> noise(0,1);
boost::variate_generator<boost::mt19937,
boost::normal_distribution<float> > nD(randgen, noise);
for (int i = 0; i < 100; i++)
{
value = nD();
// graph each value
}
}
};
Class A {
void someFunction()
{
for(int i = 1; i <=3; i++)
{
std::shared_ptr<B> b;
b.reset(new B());
b->generator();
}
}
};
我希望快速连续多次执行上述代码以生成多个图形。我还回顾了this stackoverflow问题,这个问题很相似,但有一点需要注意,当使用time(0)并快速连续调用成员函数时,你仍然可能得到相同的数字序列。
我如何克服这个问题?
编辑:我已尝试在B类中制作randgen静态,也尝试将其作为A类中的全局变量,但每次3个图形仍然相同。我也试过从GetSystemTime毫秒播种。我一定错过了什么。
答案 0 :(得分:6)
一种方法是每次执行代码时不重置随机数生成器。
创建生成器并将其播种,然后继续使用它。
假设您在同一次运行中多次调用该代码。如果您正在进行多次运行(但仍在同一秒内),则可以使用其他不同的属性(例如进程ID)来更改种子。
或者,您可以使用Windows GetSystemTime()
返回SYSTEMTIME结构,其中一个元素为毫秒,或者Linux getTimeOfDay
返回自纪元以来的微秒数。< / p>
视窗:
#include <windows.h>
SYSTEMTIME st;
GetSystemTime (&st);
// Use st.wSecond * 100 + st.wMillisecs to seed (0 thru 59999).
Linux的:
#include <sys/time.h>
struct timeval tv;
gettimeofday (&tv, NULL);
// Use tv.tv_sec * 100 + (tv.tv_usec / 1000) to seed (0 thru 59999).
答案 1 :(得分:6)
使用Boost.Random,您可以保存随机数生成器的状态 - 例如,您可以将其保存到文本文件中。这是通过流完成的。
例如,使用代码,在为生成器设定种子并运行一次之后,可以使用输出流保存状态,如下所示:
std::ofstream generator_state_file("rng.saved");
generator_state_file << randgen;
然后,当你创建了一个新的生成器时,可以使用相反的流从该文件加载状态:
std::ifstream generator_state_file("rng.saved");
generator_state_file >> randgen;
然后使用状态生成更多随机数,然后重新保存状态,依此类推。
如果您不想使用文件,也可以使用std::string
将状态保存到std::stringstream
,但我没有亲自尝试过。
答案 2 :(得分:4)
只创建一个随机数生成器,因此它只播种一次:
static boost::mt19937 randgen(static_cast<unsigned int>(std::time(0)));
答案 3 :(得分:1)
在unix上,您可以尝试从/ dev / random或/ dev / urandom中读取一些字节作为种子。您还可以尝试使用time(0)+ pid +静态计数器(或伪随机序列)的组合。
我相信Windows,您可以使用QueryPerformanceCounter
来获取高性能定时器寄存器的值。
你可以将你的mt19937 prng声明为静态或全局,这样你就永远不会失去它的状态。
您希望“快速连续多次执行上述代码以生成多个图形”传递图索引。 (例如genGraph(int graphIndex)并将此(add,xor等)与time(0)的输出结合起来。boost::mt19937 randgen(static_cast<unsigned int>(std::time(0) + graphIndex));
答案 4 :(得分:1)
一个迟到的答案:两个随机数生成器函数,用于将boost与标准方法进行比较。
<强>升压强>
#include <boost/random.hpp>
//the code that uses boost is massively non-intuitive, complex and obfuscated
bool _boost_seeded_=false;
/*--------------------*/int
boostrand(int High, int Low)
{
static boost::mt19937 random;
if (!_boost_seeded_)
{
random = boost::mt19937(time(0));
_boost_seeded_=true;
}
boost::uniform_int<> range(Low,High);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
getrandom(random, range);
return getrandom();
}
标准强>
#include <cstdlib>
#include <time.h>
//standard code is straight-forward and quite understandable
bool _stdrand_seeded_=false;
/*--------------------*/int
stdrand(int High, int Low)
{
if (!_stdrand_seeded_)
{
srand(time(0));
_stdrand_seeded_=true;
}
return ((rand() % (High - Low + 1)) + Low);
}
两种功能的结果相同,“随机性”相同。我会应用KISS原则。
答案 5 :(得分:0)
如果您不想只使用一个生成器,您可以创建一个带种子的生成器(time(0)),然后将该生成器用作其他生成器的种子。
时间(0)的分辨率为1秒。在短时间内多次使用它作为种子将创建相同的生成器。