ein*_*ica 5 c++ random enums c++11 uniform-distribution
我在很多地方使用C++随机数实用程序库.它可能不是很舒服(例如,没有任意分布的基类),但是 - 我已经学会了忍受它.
现在我碰巧需要从枚举类型中统一采样值.我知道,关于SO的问题已经存在:
然而,那一个:
假设所有枚举值都是连续的,即它不起作用
enum Color { Red = 1, Green = 2, Blue = 4 }
Run Code Online (Sandbox Code Playgroud)
我们希望以1/3的概率对这三个值中的每一个进行采样.
std::uniform_distribution<>,即它不能与您传递它的随机引擎一起使用等等.显然我不能使用std::uniform_int_distribution<Color>,如果只是因为上面的原因1.我该怎么做呢?
笔记:
以下是分布的三种实现,按复杂性升序排列:
首先,如果我们可以依赖不同的值或者可以接受重复值超重,我们可以只索引容器_values():
template<class Enum>
struct SimpleEnumDistribution
{
std::uniform_int_distribution<typename Enum::_integral> dist{0, Enum::_size() - 1};
template<class Generator> Enum operator()(Generator& g) { return Enum::_values()[dist(g)]; }
};
Run Code Online (Sandbox Code Playgroud)
否则,我们可以使用拒绝采样,预先计算枚举值范围的最小值和最大值:
template<class Enum>
struct UniformEnumDistribution
{
std::uniform_int_distribution<typename Enum::_integral> dist{
*std::min_element(Enum::_values().begin(), Enum::_values().end()),
*std::max_element(Enum::_values().begin(), Enum::_values().end())};
template<class Generator> Enum operator()(Generator& g)
{
for (;;)
if (auto value = Enum::_from_integral_nothrow(dist(g)))
return *value;
}
};
Run Code Online (Sandbox Code Playgroud)
如果这效率低下(也许枚举值稀疏),我们可以在初始化时计算一个查找表:
template<class Enum>
struct FastUniformEnumDistribution
{
std::uniform_int_distribution<std::size_t> dist;
std::array<typename Enum::_integral, Enum::_size()> values;
FastUniformEnumDistribution()
{
std::copy(Enum::_values().begin(), Enum::_values().end(), values.data());
std::sort(values.begin(), values.end());
dist.param(std::uniform_int_distribution<std::size_t>::param_type{0u, static_cast<std::size_t>(
std::distance(values.begin(), std::unique(values.begin(), values.end())) - 1)});
}
template<class Generator> Enum operator()(Generator& g)
{
return Enum::_from_integral_unchecked(values[dist(g)]);
}
};
Run Code Online (Sandbox Code Playgroud)
例子。
| 归档时间: |
|
| 查看次数: |
594 次 |
| 最近记录: |