正如标题所示,我试图找出一种使用新的C ++ 11 <random>
库生成随机数的方法。我用这段代码尝试过:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
我的代码的问题是,每次编译和运行它时,它总是生成相同的数字。所以我的问题是随机库中的其他函数可以在真正随机的情况下实现这一点吗?
对于我的特定用例,我试图获得[1, 10]
范围内的值
来自微软的Stephan T. Lavavej(stl)在Going Native上谈了如何使用新的C ++ 11随机函数以及为什么不使用rand()
。在其中,他包括一张幻灯片,基本上解决了你的问题。我已从下面的幻灯片中复制了代码。
你可以在这里看到他的全文:http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
#include <random>
#include <iostream>
int main() {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(1.0, 10.0);
for (int i=0; i<16; ++i)
std::cout << dist(mt) << "\n";
}
我们使用random_device
一次播种名为mt
的随机数生成器。 random_device()
比mt19937
慢,但它不需要播种,因为它要求来自您的操作系统的随机数据(来自不同的位置,例如RdRand)。
看看this question / answer,看来uniform_real_distribution
返回[a, b)
范围内的数字,你想要[a, b]
。要做到这一点,我们的uniform_real_distibution
应该看起来像:
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
我的'随机'库为C ++ 11随机类提供了一个高度方便的包装器。您可以使用简单的“获取”方法完成几乎所有事情。
例子:
auto val = Random::get(-10, 10); // Integer
auto val = Random::get(10.f, -10.f); // Float point
auto val = Random::get<bool>( ) // 50% to generate true
auto val = Random::get<bool>( 0.7 ) // 70% to generate true
auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator
auto it = Random::get( vec ); // return random iterator
还有更多的东西!查看github页面:
这是我刚才写的那些东西::
#include <random>
#include <chrono>
#include <thread>
using namespace std;
//==============================================================
// RANDOM BACKOFF TIME
//==============================================================
class backoff_time_t {
public:
random_device rd;
mt19937 mt;
uniform_real_distribution<double> dist;
backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {}
double rand() {
return dist(mt);
}
};
thread_local backoff_time_t backoff_time;
int main(int argc, char** argv) {
double x1 = backoff_time.rand();
double x2 = backoff_time.rand();
double x3 = backoff_time.rand();
double x4 = backoff_time.rand();
return 0;
}
~
这里有一些关于伪随机数生成器的资源。
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
基本上,计算机中的随机数需要一个种子(这个数字可以是当前的系统时间)。
更换
std::default_random_engine generator;
通过
std::default_random_engine generator(<some seed number>);
你有两种常见的情况。首先,您需要随机数,并且不要过于关注质量或执行速度。在这种情况下,请使用以下宏
#define uniform() (rand()/(RAND_MAX + 1.0))
这使得p在0到1的范围内 - epsilon(除非RAND_MAX大于double的精度,但是当你来到它时会担心它)。
int x =(int)(uniform()* N);
现在给出0到N -1的随机整数。
如果你需要其他发行版,你必须转换p。或者有时多次调用uniform()会更容易。
如果你想要可重复的行为,请使用常量种子,否则调用time()种子。
现在,如果您对质量或运行时性能感到困扰,请重写uniform()。但否则不要触摸代码。始终将uniform()保持在0到1减去epsilon。现在,您可以包装C ++随机数库以创建更好的uniform(),但这是一种中级选项。如果您对RNG的特性感到困扰,那么也需要投入一些时间来了解底层方法的工作原理,然后提供一个。因此,您可以完全控制代码,并且可以保证使用相同的种子,序列将始终完全相同,无论平台或您链接到哪个版本的C ++。