C++标准库提供了一系列随机数分布生成器,每个生成器都有自己的属性。在本示例中,我们将通过创建它们的输出直方图来比较不同的选项。
如何做……
与随机数引擎类似,分布生成器也有一些共同的接口元素。但与随机数引擎不同,分布生成器有各种各样的属性可以设置。我们可以创建一个模板函数来打印各种分布的直方图,但各种分布生成器的初始化差异很大:
我们首先定义一些常量:
constexpr size_t n_samples{ 10 * 1000 };
constexpr size_t n_max{ 50 };
n_samples 常量是每种直方图要生成的样本数——在这种情况下,是10,000。
n_max 常量在生成直方图时用作除数。
我们的直方图函数接受一个分布生成器作为参数,并打印该分布算法的直方图:
void dist_histogram(auto distro, const string_view& dist_name) {
std::default_random_engine rng{};
map<long, size_t> m;
// 创建直方图映射
for(size_t i{}; i < n_samples; ++i)
++m[(long)distro(rng)];
// 打印直方图
// ... (省略了查找最大元素和计算除数的代码)
cout << format("{}:\n", dist_name);
for (const auto [randval, count] : m) {
if (count < max_elm / n_max) continue;
cout << format("{:3}:{:*<{}}\n", randval, ' ', count / max_div);
}
}
dist_histogram() 函数使用映射来存储直方图,然后在控制台上显示一系列星号形式的直方图。
我们从main()中调用dist_histogram(),如下所示:
int main() {
dist_histogram(std::uniform_int_distribution<int>{0, 9}, "uniform_int_distribution");
dist_histogram(std::normal_distribution<double>{0.0, 2.0}, "normal_distribution");
// ... (省略了其他分布生成器的调用)
}
调用dist_histogram()函数比调用随机数生成器时更复杂。每个随机分布类根据其算法有不同的参数集。
完整的列表请参考GitHub存档中的distribution.cpp文件。
输出:
每个分布算法产生的输出都非常不同。您可能想要对每个随机分布生成器的不同选项进行实验。
它是如何工作的……
每个分布生成器都有一个函数对象,该函数对象返回随机分布中的下一个值:
result_type operator()( Generator& g );
该函数对象接受一个随机数生成器(RNG)对象作为参数:
std::default_random_engine rng{};
map<long, size_t> m;
for (size_t i{}; i < n_samples; ++i) ++m[(long)distro(rng)];
对于我们的目的,我们使用std::default_random_engine作为我们的RNG。
与RNG直方图一样,这是可视化随机库中可用的各种随机分布算法的有用工具。您可能想要对每种算法可用的各种参数进行实验。