我有一个名为 RandomNumberGenerator 的类,我想用 mt19937算法生成一个随机数。
我正在创建一个 random_device 的对象作为种子。
编译时,我收到的错误是:
"No member named generate in std::__1::random_device".
我无法理解错误。也许我在初始化 random_device 和 mt19937 的对象的方式上做错了,但我无法弄清楚错误是什么。
感谢一些帮助..
RandomNumberGenerator.h
class RandomNumberGenerator
{
static std::random_device m_rd;
static std::mt19937 m_rng;
public:
static double getRandomNumber(const double& rangeStart, const double& rangeEnd);
};
RandomNumberGenerator.cpp
#include "RandomNumberGenerator.h"
std::random_device RandomNumberGenerator::m_rd;
std::mt19937 RandomNumberGenerator::m_rng(RandomNumberGenerator::m_rd);
double RandomNumberGenerator::getRandomNumber(const double& rangeStart, const double& rangeEnd)
{
std::uniform_real_distribution<> randomizer(rangeStart, rangeEnd);
return randomizer(m_rng);
}
答案 0 :(得分:4)
std::mt19937 RandomNumberGenerator::m_rng(RandomNumberGenerator::m_rd);
以上行是发送实例而不是种子。因此,它必须具有generate
函数来提供它没有的种子。只需更改该行即可调用仿函数,一切顺利。
std::mt19937 RandomNumberGenerator::m_rng(RandomNumberGenerator::m_rd());
注意:强>
另外需要注意的一项是,您要在每次通话时分配新的std::uniform_real_distribution
。虽然分布对象的重量很轻,但只要rangeStart
和rangeEnd
对后续调用保持不变,请考虑将其设置为静态。但是,如果您做出决定,初始化范围值将是一个更艰难的决定。
如果您的程序在整个生命周期内都没有使用此类,请考虑将其作为实例类,并在ctor上取范围,以便在生成数字后进行完全清理。
希望这有帮助。
修改强>
如果你肯定希望它是静态的,另一种选择是分配并完全清理函数中的所有对象,这些对象将填充所有需要的值,类似于以下内容:
template<typename T, typename DISTRIBUTION>
static void fill(T* buffer, uint32_t const count, T const min, T const max)
{
ASSERT(buffer);
ASSERT(count);
ASSERT(max > min);
std::random_device randomDevice;
std::mt19937_64 twisterEngine { randomDevice() };
DISTRIBUTION<T> distribution(min, max);
for (uint32_t bufferLocation = 0; bufferLocation < count; ++bufferLocation)
buffer[bufferLocation] = distribution(twisterEngine);
}
然后将其用于以下各种类型:
uint32_t const COUNT = 31u;
double realValues[COUNT];
uint32_t intValues[COUNT];
RandomNumberGenerator::fill<double, std::uniform_real_distribution<double>>(&realValues[0], COUNT, 100.0, 200.0);
RandomNumberGenerator::fill<uint32_t, std::uniform_int_distribution<uint32_t>>(intValues, COUNT, 100u, 200u);
如果这看起来像一个丑陋的界面,那么将fill
设为私有,并提供干净的公共方法,以提供您希望支持的几种类型。