使用C++ 11随机库生成随机数

sma*_*c89 128 c++ random range c++11

正如标题所示,我试图找出一种使用新的C++ 11 <random>库生成随机数的方法.我用这段代码尝试过:

std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
Run Code Online (Sandbox Code Playgroud)

我的代码的问题是,每次编译和运行它时,它总是生成相同的数字.所以我的问题是随机库中的其他函数可以在真正随机的情况下实现这一点吗?

对于我的特定用例,我试图获得该范围内的值 [1, 10]

Bil*_*nch 183

来自微软的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";
}
Run Code Online (Sandbox Code Playgroud)

我们使用random_device一次种子命名的随机数生成器mt.random_device()mt19937它慢,但它不需要播种,因为它要求来自操作系统的随机数据(来自不同的位置,例如RdRand).


看看这个问题/答案,似乎会uniform_real_distribution返回[a, b)您想要的范围内的数字[a, b].要做到这一点,我们uniform_real_distibution应该看起来像:

std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
Run Code Online (Sandbox Code Playgroud)

  • 对于大多数应用来说,`nextafter`调用是过度的.在端点上随机"双重"着陆的可能性非常小,以至于包含和排除它之间没有实际区别. (20认同)
  • @chris我们都知道矢量和地图之间的区别,并不是每个人都知道mt19937和ranlux24之间的区别,如果有人设法成为程序员而不知道矢量和字典是什么,也许他们应该有一个`std :: default_container `,希望没有人认为自己的程序员不知道差异,很多脚本语言都有默认的地图类型结构,可以用各种各样的方式实现,用户可能不知道 (4认同)
  • @aaronman:我正在听 STL 的演讲,他明确不喜欢 `default_random_engine` 的存在。 (3认同)
  • @chris不相关(但是你打开了门),你的`std :: vector`类比在这里不起作用,因为`std :: vector`**实际上是一个很好的默认值,因为CPU缓存.它甚至优于`std :: list`插入中间.即使您确实理解了所有容器,并且可以根据算法的复杂性做出明智的决定,这也是事实. (3认同)
  • 由于该问题要求使用最通用的方式来生成随机数,因此您可能只想使用default_random_engine,根据c ++入门,它被认为是最有用的一种实现方式 (2认同)
  • @aaronman,至少有了 mt19937,你就知道你得到了一些好东西。这就像在几乎所有情况下都默认为 `std::vector`。如果您知道自己需要什么以及其他容器提供什么,您就可以做出明智的决定,但我们会一直告诉人们使用矢量,即使他们不知道所有不同的容器类型是什么。公平地说,没有 `std::default_container`,但对我来说,这似乎是类似的情况。 (2认同)

Ily*_*huk 21

我的'随机'库为C++ 11随机类提供了一个高度方便的包装器.您可以使用简单的"获取"方法完成几乎所有事情.

例子:

  1. 范围内的随机数

    auto val = Random::get(-10, 10); // Integer
    auto val = Random::get(10.f, -10.f); // Float point
    
    Run Code Online (Sandbox Code Playgroud)
  2. 随机布尔值

    auto val = Random::get<bool>( ) // 50% to generate true
    auto val = Random::get<bool>( 0.7 ) // 70% to generate true
    
    Run Code Online (Sandbox Code Playgroud)
  3. 来自std :: initilizer_list的随机值

    auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
    
    Run Code Online (Sandbox Code Playgroud)
  4. 来自迭代器范围或所有容器的随机迭代器

    auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator
    auto it = Random::get( vec ); // return random iterator
    
    Run Code Online (Sandbox Code Playgroud)

还有更多的东西!查看github页面:

https://github.com/effolkronium/random


Iva*_*vic 8

我红上述所有的东西,关于它40个其它页面与类似于C ++这样并观看了由斯蒂芬T. Lavavej“STL”的视频 仍然不知道随机数是如何工作的实践,所以我花了整整周日弄清楚它的全部内容以及它的工作原理和使用方式。

在我看来,STL 关于“不再使用 srand”是正确的,他在视频2 中很好地解释了这一点。他还建议使用:

a) void random_device_uniform()-- 用于加密生成但速度较慢(来自我的示例)

b) 具有mt19937-- 更快、能够创建种子、未加密的示例


我拿出了我可以访问的所有声称的 c++11 书籍,并发现像 Breymann(2015)这样的德国作者仍然使用

srand( time( 0 ) );
srand( static_cast<unsigned int>(time(nullptr))); or
srand( static_cast<unsigned int>(time(NULL))); or
Run Code Online (Sandbox Code Playgroud)

只是用<random>而不是<time> and <cstdlib>#includes - 所以要小心地从一本书中学习:)。

含义 - 自 c++11 起不应使用,因为:

程序通常需要一个随机数源。在新标准之前,C 和 C++ 都依赖于一个名为 rand 的简单 C 库函数。该函数生成伪随机整数,这些整数均匀分布在从 0 到至少为 32767 的系统相关最大值的范围内。 rand 函数有几个问题: 许多(如果不是大多数)程序需要与一种由兰特生产。某些应用程序需要随机浮点数。一些程序需要反映非均匀分布的数字。程序员在尝试转换由 rand 生成的数字的范围、类型或分布时,通常会引入非随机性。(引自 Lippmans C++ 入门第五版 2012)


我终于在 Bjarne Stroustrups 新书的 20 本书中找到了最好的解释——他应该知道他的东西——在“C++ 2019 之旅”、“使用 C++ 2016 的编程原则和实践”和“C++ 编程语言第 4 版”中2014”以及“Lippmans C++ 入门第五版 2012”中的一些示例:

它真的很简单,因为随机数生成器由两部分组成: (1) 一个生成随机或伪随机值序列的引擎。(2) 将这些值映射到某个范围内的数学分布的分布。


尽管微软的 STL 家伙有意见,但 Bjarne Stroustrups 写道:

在 中,标准库提供随机数引擎和分布(第 24.7 节)。默认情况下使用 default_random_engine ,选择它是为了广泛的适用性和低成本。

void die_roll()例子与比亚Stroustrups -好主意生成引擎和分布using (更多的回合,在这里)


为了能够在 此处实际使用标准库提供的随机数生成器,将<random> 一些带有不同示例的可执行代码减少到最低限度,希望为你们节省时间和金钱:

srand( time( 0 ) );
srand( static_cast<unsigned int>(time(nullptr))); or
srand( static_cast<unsigned int>(time(NULL))); or
Run Code Online (Sandbox Code Playgroud)

我认为这一切都加起来了,就像我说的那样,我花了很多时间阅读并把它提炼成这些例子——如果你有更多关于数字生成的东西,我很高兴通过 pm 或评论部分听到这个消息并将在必要时添加它或编辑此帖子。布尔值


归档时间:

查看次数:

111955 次

最近记录:

5 年,9 月 前