我正在研究包含随机初始状态的算法。因此,每次运行时,此算法的输出都不稳健。这会给我带来很多麻烦,因为我收到错误的输出并想调试它以查看问题所在,因为当我再次运行它时,由于算法的随机因素,问题可能无法重新生成。我正在使用C ++随机生成器如下:
std::random_device rd;
std::mt19937 rnd_generator(rd());
std::uniform_int_distribution<> rnd_distribution(0, data_size - 1);
auto get_random_index = [&](){
return rnd_distribution(rnd_generator);
};
我如何模仿这个函数生成的最后一个随机序列?例如,我可以给它一些静态种子,我可以重新输入它并获得完全相同的随机序列吗?我在问,因为我觉得这是常见的问题所以可能有一些好的和有效的知名方式。
答案 0 :(得分:6)
将调用结果保存到rd()
并使用该结果在下一次传递时初始化rnd_generator
示例:
#include <iostream>
#include <random>
auto main() -> int
{
using namespace std;
random_device rd;
auto seed = rd();
for (int pass = 0 ; pass < 3 ; ++pass)
{
mt19937 rnd_generator(seed);
uniform_int_distribution<> rnd_distribution(0, 9);
for (int i = 0 ; i < 5 ; ++i)
{
cout << rnd_distribution(rnd_generator) << ", ";
}
cout << endl;
}
return 0;
}
示例输出:
9, 5, 3, 5, 4,
9, 5, 3, 5, 4,
9, 5, 3, 5, 4,
答案 1 :(得分:3)
std::mt19937 rnd_generator(rd());
每次使用不同的随机种子为PRNG播种。如果您想在测试时使用相同的随机序列,那么您只需硬编码种子而不是使用rd()
。
std::mt19937 rnd_generator(0); // each run will use the seed value of 0
答案 2 :(得分:1)
您可以将RNG引擎打印到std::ostream
进行序列化,然后从std::istream
读取它以对其进行反序列化。请注意,由于您使用了std::uniform_int_distribution<>
,因此在使用不同的编译器时,不会重现相同的数字序列。
答案 3 :(得分:0)
std::mt19937
是您随机性的来源。使用consitant种子(我认为是uint_least32_t
)进行测试是有道理的,但使用random_device()
(这是一个随机的&#39}的功能也很好。 ; uint_least32_t
)。
问题是你在错误的地方创造它。设计你的代码,使有趣的逻辑与随机源分开。提供随机性调用者/类创建者问题称为Dependency Injection并使代码可测试。
这样的事情:
class ThingDooer final
{
std::mt19937 _prng;
public:
// ThingDooer(uint_least32_t seed);
// ThingDooer() : ThingDoor(std::_Random_device()) {}; // these two or
ThingDooer(std::mt19937 prng);
void DoThing();
};
我在C ++(It's terrible and reads like C#)中做的第一件事就是将std::mt19937
包装在IRandom
接口中,以便我可以提供具有精确指定数字的模拟实现。当然,这可能对你来说太过分了。永远不会拖着嘲弄的图书馆,我仍然会想到我们可能会嘲笑的东西:
class RandallRandom : public IRandom final
{
public:
RandallRandom();
int32_t Next() { return 4; }
};