C++ 11引入了<random>带有随机数引擎和随机分布声明的头文件.那很好 - 取代那些用途的时间rand()往往会以各种方式出现问题.但是,如何更换它似乎远非显而易见
srand(n);
// ...
int r = rand();
Run Code Online (Sandbox Code Playgroud)
基于声明,似乎可以构建如下的统一分布:
std::default_random_engine engine;
engine.seed(n);
std::uniform_int_distribution<> distribution;
auto rand = [&](){ return distribution(engine); }
Run Code Online (Sandbox Code Playgroud)
这种方法似乎相当复杂,并且肯定是我不记得的东西,不像使用srand()和rand().我知道N4531,但即使这样看起来仍然非常复杂.
是否有一个相当简单的方式来代替srand()和rand()?
在Stackoverflow上,有很多关于从a-priory未知范围生成均匀分布的整数的问题.例如
典型的解决方案是这样的:
inline std::mt19937 &engine()
{
thread_local std::mt19937 eng;
return eng;
}
int get_int_from_range(int from, int to)
{
std::uniform_int_distribution<int> dist(from, to);
return dist(engine());
}
Run Code Online (Sandbox Code Playgroud)
鉴于分布应该是一个轻量级对象并且没有性能问题需要多次重新创建它,看起来即使是简单的分发也可能很好并且通常会有一些内部状态.
所以我想知道是否通过不断重置它来干扰分布如何工作(即在每次调用时重新创建分布get_int_from_range)我得到了正确分布的结果.
Pete Becker和Steve Jessop之间进行了长时间的讨论,但没有最后的说法.在另一个问题中(我应该保留随机分布对象实例还是可以随时重新创建它?)内部状态的"问题"似乎并不重要.
C++标准是否对此主题做出了任何保证?
以下实现(来自N4316 - std :: rand替换)是否更可靠?
int get_int_from_range(int from, int to)
{
using distribution_type = std::uniform_int_distribution<int>;
using param_type = typename distribution_type::param_type;
thread_local std::uniform_int_distribution<int> dist;
return dist(engine(), param_type(from, to));
}
Run Code Online (Sandbox Code Playgroud)
编辑
这重用了分发的可能的内部状态,但它很复杂,我不确定它是否值得麻烦:
int get_int_from_range(int from, int to)
{
using …Run Code Online (Sandbox Code Playgroud) 我刚刚开始<random>第一次使用C++ 11的标题,但仍有一些东西看起来有点神秘.这个问题是关于完成一项非常简单的任务的预期的,惯用的,最佳实践方法.
目前,在我的代码的一部分我有这样的事情:
std::default_random_engine eng {std::random_device{}()};
std::uniform_int_distribution<> random_up_to_A {0, A};
std::uniform_int_distribution<> random_up_to_B {0, B};
std::uniform_int_distribution<> random_up_to_some_other_constant {0, some_other_constant};
Run Code Online (Sandbox Code Playgroud)
然后当我想要一个0和BI之间的整数调用random_up_to_B(eng).
由于这开始看起来有点傻,我想实现一个函数rnd,rnd(n, eng)返回0到n之间的随机整数.
像下面这样的东西应该工作
template <class URNG>
int rnd(int n, URNG &eng) {
std::uniform_int_distribution<> dist {0, n};
return dist(eng);
}
Run Code Online (Sandbox Code Playgroud)
但这涉及每次创建一个新的分发对象,我得到的印象不是你应该这样做的方式.
所以我的问题是,使用<random>标题提供的抽象来完成这个简单任务的预期最佳实践方法是什么?我问,因为我一定要做比以后更复杂的事情,我想确保我以正确的方式使用这个系统.
问:如何从a-priory未知范围生成(多个)均匀分布的整数?在性能方面(生成的数字的数百万),首选的方式是什么?
上下文:在我的应用程序中,我必须在许多地方生成许多伪随机数.我使用单例模式生成器来保持应用程序运行的可重复性.在我的情况下,分布总是一致的,但问题是在C++ 11样式中预先制作分发对象有太多可能的范围.
我尝试过:有两个明显的解决方案,第一个是一次性分配对象,第二个是使用modulo将随机数从最宽的范围转换为所需的范围.但不知何故,我怀疑这些是最好的:)
#include <random>
#include <iostream>
#include "limits.h"
using namespace std;
mt19937 mt;
uniform_int_distribution<int> * fixedDist;
uniform_int_distribution<int> * variableDist;
// this version creates and delete dist after just one use
int getIntFromRange1(int from, int to){
variableDist = new uniform_int_distribution<int>(from,to);
int num = (*variableDist)(mt);
delete variableDist;
return num;
}
// this version contains modulo
int getIntFromRange2(int from, int to){
int num = (*fixedDist)(mt);
int diff = to - from;
num = num % diff;
return num + from;
} …Run Code Online (Sandbox Code Playgroud) 问题是我需要生成0到999之间的随机整数(用于调查数学猜想).所有值都需要具有相同的概率.
我已经尝试了rand(),但是RAND_MAX在32767(在我的编译器上)这意味着只需rand() % 1000要将第一个1-767的线索更有可能出现(并且假设所有可能性rand()在第一个位置具有相同的概率).
我正在使用Windows所以/dev/random不是一个选择.
我有一个问题,我想std::uniform_int_distribution在一个结构中创建一个,然后再给出它的范围。下面是我想要的。
#include <random>
#include <iostream>
std::random_device rd;
std::mt19937 gen(rd());
struct group_s {
int k;
std::uniform_int_distribution<> dis;
} group;
int main()
{
group.dis(0,19);
std::cout << group.dis(gen) << ' ';
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
no match for call to '(std::uniform_int_distribution<>) (int, int)'
cpu_group.dis(0,19);
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?