Boost C++ 库

...世界上最受尊敬和专家设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

教程

生成一定范围内的整数
生成具有不同概率的整数
生成随机密码
生成准随机线球交点

此示例的源代码请参见 die.cpp。 首先,我们包含 mt19937uniform_int_distribution 所需的头文件。

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

我们使用默认种子的 mt19937 作为随机源。 每次运行程序时,生成的数字都将相同。 一种常见的更改方法是用当前时间(在 ctime 中定义的 std::time(0))作为种子。

boost::random::mt19937 gen;

[Note] 注意

我们在这里使用一个全局生成器对象。 这很重要,因为我们不想在每次调用时都创建一个新的伪随机数生成器

现在我们可以定义一个模拟普通六面骰子的函数。

int roll_die() {
    1boost::random::uniform_int_distribution<> dist(1, 6);
    2return dist(gen);
}

1

mt19937 生成范围为 [0, 232-1] 的整数。 但是,我们希望数字在 [1, 6] 范围内。 分布 uniform_int_distribution 执行此转换。

[Warning] 警告

与常见的 C++ 用法相反,uniform_int_distribution 不采用半开范围。 相反,它采用闭合范围。 给定参数 1 和 6,uniform_int_distribution 可以生成 1、2、3、4、5 或 6 中的任何值。

2

分布是一个函数对象。 我们通过使用生成器调用 dist 来生成随机数。

此示例的源代码请参见 weighted_die.cpp

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/discrete_distribution.hpp>

boost::mt19937 gen;

这一次,掷出 1 的概率为 50% (!),而不是公平的骰子。 其他五个面的可能性均等。

discrete_distribution 通过允许我们为每个可能的结果分配权重,可以很好地在这里工作。

[Tip] 提示

如果您的编译器支持 std::initializer_list,则可以使用权重直接初始化 discrete_distribution

double probabilities[] = {
    0.5, 0.1, 0.1, 0.1, 0.1, 0.1
};
boost::random::discrete_distribution<> dist(probabilities);

现在定义一个模拟掷骰子的函数。

int roll_weighted_die() {
    1return dist(gen) + 1;
}

1

加 1 以确保结果在 [1,6] 范围内而不是 [0,5] 范围内。

此示例的源代码请参见 password.cpp

此示例演示如何生成一个 8 个字符的随机密码。

#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <iostream>

int main() {
    1std::string chars(
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "1234567890"
        "!@#$%^&*()"
        "`~-_=+[{]}\\|;:'\",<.>/? ");
    2boost::random::random_device rng;
    3boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
    for(int i = 0; i < 8; ++i) {
        std::cout << chars[index_dist(rng)];
    }
    std::cout << std::endl;
}

1

我们首先定义我们将允许的字符。 这几乎只是标准键盘上的字符。

2

我们使用 random_device 作为熵源,因为我们希望密码是不可预测的。

3

最后,我们从字符串中选择 8 个随机字符并将它们打印到 cout。

此示例的源代码请参见 intersections.cpp

此示例演示如何在 S2 球体上生成准随机分布的弦入口和出口点。

首先,我们包含 niederreiter_base2uniform_01 分布所需的头文件。

#include <boost/random/niederreiter_base2.hpp>
#include <boost/random/uniform_01.hpp>

#include <boost/math/constants/constants.hpp>

#include <boost/tuple/tuple.hpp>

我们使用 4 维 niederreiter_base2 作为随机源。

boost::random::niederreiter_base2 gen(4);


int main()
{
  typedef boost::tuple<double, double, double> point_t;

  const std::size_t n_points = 100; // we will generate 100 points

  std::vector<point_t> points;
  points.reserve(n_points);

  1boost::random::uniform_01<double> dist;

  for (std::size_t i = 0; i != n_points; ++i)
  {

使用 J. Rovira 等人在 2005 年发表的论文“Point sampling with uniformly distributed lines”中的公式来计算球体表面上均匀分布的弦入口和出口点。

double cos_theta = 1 - 2 * dist(gen);
double sin_theta = std::sqrt(1 - cos_theta * cos_theta);
double phi = boost::math::constants::two_pi<double>() * dist(gen);
double sin_phi = std::sin(phi), cos_phi = std::cos(phi);

point_t point_on_sphere(sin_theta*sin_phi, cos_theta, sin_theta*cos_phi);

这里我们假设我们的球体是位于原点的单位球体。 如果您的球体不同,那么现在是缩放和平移 point_on_sphere 的时候了。

  points.push_back(point_on_sphere);
}

向量 points 现在保存生成的球体上的 3D 点。

  return 0;
}

1

niederreiter_base2 生成范围为 [0, 264-1] 的整数。 但是,我们希望数字在 [0, 1) 范围内。 分布 uniform_01 执行此转换。


PrevUpHomeNext