简短的背景信息
例如,生成具有特定分布的随机数的一种方法是从区间 [0, 1) 生成均匀分布的随机数,然后对这些数字应用一些数学运算以将它们塑造成所需的分布。所以你有两个对象:一个来自 [0, 1) 的随机数生成器和一个分布对象,它采用均匀分布的随机数并在所需(例如正态)分布中吐出随机数。
为什么通过引用传递生成器
代码中的var_nor
对象将生成器rnd
与正态分布耦合nd
。您必须通过引用传递您的生成器,这是&
模板参数中的。这真的很重要,因为随机数生成器有一个内部状态,它可以从中计算下一个(伪)随机数。如果您不通过引用传递生成器,您将创建它的副本,这可能会导致代码始终创建相同的随机数。请参阅此博客文章作为示例。
为什么variate_generator
是必要的
现在到了部分,为什么不直接使用生成器的分布。如果您尝试以下代码
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
int main()
{
boost::mt19937 generator;
boost::normal_distribution<> distribution(0.0, 1.0);
// WARNING: THIS DOES NOT WORK AS MIGHT BE EXPECTED!!
for (int i = 0; i < 100; ++i)
std::cout << distribution(generator) << std::endl;
return 0;
}
你会看到,它只输出NaN
s(我已经用 Boost 1.46 测试过)。原因是梅森扭曲器返回一个均匀分布的整数随机数。但是,大多数(甚至可能是所有)连续分布都需要[0, 1) 范围内的浮点随机数。Boost 文档中给出的示例之所以有效,是因为uniform_int_distribution
它是一个离散分布,因此可以处理整数 RNG。
注意:我还没有尝试过使用更新版本的 Boost 的代码。当然,如果将离散 RNG 与连续分布一起使用,编译器会抛出错误会很好。