所以我有一个Random对象:
typedef unsigned int uint32;
class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}
private:
uint32 DrawNumber();
std::mt19937 eng{std::random_device{}()};
std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};
uint32 Random::DrawNumber()
{
return uniform_dist(eng);
}
我可以通过其他函数或其他方式改变分布的上限的最佳方式是什么?
(也愿意就其他风格问题提出建议)
答案 0 :(得分:38)
分发对象很轻量级。当您需要随机数时,只需构建一个新的分布。我在游戏引擎中使用这种方法,并且在基准测试之后,它与使用好的旧rand()
相当。
此外,我已经询问如何改变GoingNative 2013直播流的发行范围,标准委员会成员Stephen T. Lavavej建议简单地创建新的发行版,因为它不应该是一个表演问题。
以下是我编写代码的方法:
using uint32 = unsigned int;
class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}
uint32 DrawNumber(uint32 min, uint32 max);
private:
std::mt19937 eng{std::random_device{}()};
};
uint32 Random::DrawNumber(uint32 min, uint32 max)
{
return std::uniform_int_distribution<uint32>{min, max}(eng);
}
答案 1 :(得分:8)
您只需创建std::uniform_int_distribution<uint32>::param_type
并使用param()
方法修改范围即可。您可以使用decltype
:
decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
答案 2 :(得分:6)
我正在为我的例子制作DrawNumber
函数public
。您可以提供带有上限的重载,然后将新的uniform_int_distribution::param_type
传递给uniform_int_distribution::operator()
可以使用与相应分布相同的参数构造param_type
。
来自N3337,§26.5.1.6/ 9 [rand.req.dist]
对于
D
的每个构造函数,它们采用与分布参数相对应的参数,P
应具有相应的构造函数,这些构造函数具有相同的要求并且在数量,类型和默认值方面具有相同的参数。此外,对于返回与分布参数对应的值的D
的每个成员函数,P
应具有相同的成员函数,具有相同的名称,类型和语义。
其中D
是随机数分布函数对象的类型,P
是由D
关联的param_type
#include <iostream>
#include <random>
typedef unsigned int uint32;
class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}
uint32 DrawNumber();
uint32 DrawNumber(uint32 ub);
private:
std::mt19937 eng{std::random_device{}()};
std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};
uint32 Random::DrawNumber()
{
return uniform_dist(eng);
}
uint32 Random::DrawNumber(uint32 ub)
{
return uniform_dist(eng, decltype(uniform_dist)::param_type(0, ub));
}
int main()
{
Random r;
std::cout << r.DrawNumber() << std::endl;
std::cout << r.DrawNumber(42) << std::endl;
}