10

我正在努力将 R 代码实现为 C++,以便它运行得更快,但我在实现 mersenne twister 时遇到了困难。我只希望生成 (0,1) 之间的值。这是我与这个问题有关的内容。

#include <random>

std::mt19937 generator (123);

std::cout << "Random value: " << generator() << std:: endl;

我尝试除以RAND_MAX,但这并没有产生我正在寻找的值。

提前致谢。

4

3 回答 3

20

在 C++11 中,“(伪)随机生成器”和“概率分布”的概念是分开的,这是有充分理由的。

你想要的可以通过以下几行来实现:

  std::mt19937 generator (123);
  std::uniform_real_distribution<double> dis(0.0, 1.0);

  double randomRealBetweenZeroAndOne = dis(generator);

如果您想了解为什么这种分离是必要的,以及为什么在生成器的输出上使用标准除法/范围操作是一个坏主意,请观看此视频

于 2014-04-07T21:44:50.110 回答
8

您可能需要考虑这样的代码:

// For pseudo-random number generators and distributions
#include <random> 

...
    
// Use random_device to generate a seed for Mersenne twister engine.
std::random_device rd{};    

// Use Mersenne twister engine to generate pseudo-random numbers.
std::mt19937 engine{rd()};

// "Filter" MT engine's output to generate pseudo-random double values,
// **uniformly distributed** on the closed interval [0, 1].
// (Note that the range is [inclusive, inclusive].)
std::uniform_real_distribution<double> dist{0.0, 1.0};

// Generate pseudo-random number.
double x = dist(engine);

有关在 C++ 中生成伪随机数的更多详细信息(包括不好的原因rand(),请参阅Stephan T. Lavavej的此视频(来自Going Native 2013):

rand()被认为是有害的

于 2014-04-08T11:09:15.977 回答
1

std::mt19937 不像 rand() 那样在 0 和 RAND_MAX 之间生成,而是在 0 和 2^32-1 之间生成

顺便说一句,该类提供了 min() 和 max() 值!

您需要将值转换为双精度,减去 min() 并除以 max()-min()

uint32_t val;
val << generator;
double doubleval = ((double)val - generator::min())/(generator::max()-generator::min());

或(不太通用)

uint32_t val;
val << generator;
double doubleval = (double)val * (1.0 / std::numeric_limits<std::uint32_t>::max());
于 2014-04-07T21:39:28.570 回答