提问者:小点点

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


正如标题所暗示的,我试图找到一种使用新的C++11库生成随机数的方法。 我用以下代码尝试过:

std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);

我的代码的问题是,每次编译和运行它时,它总是生成相同的数字。 所以我的问题是,随机库中还有哪些功能可以在真正随机的同时完成这一点?

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


共3个答案

匿名用户

来自微软的Stephan T.Lavavej(stl)在Going Native上做了一次关于如何使用新的C++11随机函数以及为什么不使用rand()的演讲。 在里面,他包括了一张幻灯片,基本上解决了你的问题。 我从下面的幻灯片中复制了代码。

你可以在这里看到他的演讲全文:http://channel9.msdn.com/events/goingnative/2013/rand-consexted-ballight

#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慢,但它不需要被植入种子,因为它从操作系统请求随机数据(这些数据将来自不同的位置,例如RDROND)。

查看此问题/答案,Uniform_Real_Distribution似乎返回了一个[a,b)范围内的数字,您需要[a,b]的位置。为此,我们的Uniform_Real_Distribution实际上应该如下所示:

std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));

匿名用户

我的“random”库提供了一个非常方便的C++11随机类的包装器。 你可以用一个简单的'get'方法做几乎所有的事情。

示例:

>

  • 范围内的随机数

    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
    

    来自std::initilizer_list的随机值

    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页面:

    https://github.com/effolkronium/random

  • 匿名用户

    我把上面所有的东西都翻红了,还有大约40页用C++写的,然后看了Stephan T.Lavavej的视频“STL”,我仍然不知道随机数在实践中是如何工作的,所以我花了整整一个星期天来弄清楚它的全部内容,它的工作原理和使用方法。

    在我看来,STL关于“不再使用srand”的说法是对的,他在视频2中解释得很好。 他还建议使用:

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

    b)MT19937示例--速度更快,能够创建种子,不加密

    我拿出了所有我能接触到的C++11书,找到了F.E。 像Breymann(2015)这样的德国作者仍然使用

    srand( time( 0 ) );
    srand( static_cast<unsigned int>(time(nullptr))); or
    srand( static_cast<unsigned int>(time(NULL))); or
    

    只使用而不是#includings-所以请注意只从一本书中学习:)。

    意思-从C++11开始就不应该使用了,因为:

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

    我终于在Bjarne Stroustrups的20本书中找到了最好的解释--他应该知道他的东西--在《2019年C++之旅》,《2016年C++编程原则和实践》和《2014年C++编程语言第四版》中,还有《2012年Lippmans C++入门第五版》中的一些例子:

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

    尽管Microsofts STL guy有这样的看法,Bjarne Stroustrups写道:

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

    void die_roll()示例来自Bjarne Strousstrups--使用生成引擎和发行版的好主意(此处更详细)。

    为了能够在中实际使用标准库提供的随机数生成器,这里有一些带有不同示例的可执行代码,这些代码减少到最小的必要程度,希望能为你们节省时间和金钱:

        #include <random>     //random engine, random distribution
        #include <iostream>   //cout
        #include <functional> //to use bind
    
        using namespace std;
    
    
        void space() //for visibility reasons if you execute the stuff
        {
           cout << "\n" << endl;
           for (int i = 0; i < 20; ++i)
           cout << "###";
           cout << "\n" << endl;
        }
    
        void uniform_default()
        {
        // uniformly distributed from 0 to 6 inclusive
            uniform_int_distribution<size_t> u (0, 6);
            default_random_engine e;  // generates unsigned random integers
    
        for (size_t i = 0; i < 10; ++i)
            // u uses e as a source of numbers
            // each call returns a uniformly distributed value in the specified range
            cout << u(e) << " ";
        }
    
        void random_device_uniform()
        {
             space();
             cout << "random device & uniform_int_distribution" << endl;
    
             random_device engn;
             uniform_int_distribution<size_t> dist(1, 6);
    
             for (int i=0; i<10; ++i)
             cout << dist(engn) << ' ';
        }
    
        void die_roll()
        {
            space();
            cout << "default_random_engine and Uniform_int_distribution" << endl;
    
        using my_engine = default_random_engine;
        using my_distribution = uniform_int_distribution<size_t>;
    
            my_engine rd {};
            my_distribution one_to_six {1, 6};
    
            auto die = bind(one_to_six,rd); // the default engine    for (int i = 0; i<10; ++i)
    
            for (int i = 0; i <10; ++i)
            cout << die() << ' ';
    
        }
    
    
        void uniform_default_int()
        {
           space();
           cout << "uniform default int" << endl;
    
           default_random_engine engn;
           uniform_int_distribution<size_t> dist(1, 6);
    
            for (int i = 0; i<10; ++i)
            cout << dist(engn) << ' ';
        }
    
        void mersenne_twister_engine_seed()
        {
            space();
            cout << "mersenne twister engine with seed 1234" << endl;
    
            //mt19937 dist (1234);  //for 32 bit systems
            mt19937_64 dist (1234); //for 64 bit systems
    
            for (int i = 0; i<10; ++i)
            cout << dist() << ' ';
        }
    
    
        void random_seed_mt19937_2()
        {
            space();
            cout << "mersenne twister split up in two with seed 1234" << endl;
    
            mt19937 dist(1234);
            mt19937 engn(dist);
    
            for (int i = 0; i < 10; ++i)
            cout << dist() << ' ';
    
            cout << endl;
    
            for (int j = 0; j < 10; ++j)
            cout << engn() << ' ';
        }
    
    
    
        int main()
        {
                uniform_default(); 
                random_device_uniform();
                die_roll();
                random_device_uniform();
                mersenne_twister_engine_seed();
                random_seed_mt19937_2();
            return 0;
        }
    

    我认为这一切都加起来了,就像我说的,它花了我大量的阅读和时间来提炼它的例子-如果你有更多关于数字生成的东西,我很高兴听到通过pm或在评论部分,并将添加它,如果有必要或编辑这篇文章。 布尔

    相关问题


    MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++11|机库|生成|随机数)' ORDER BY qid DESC LIMIT 20
    MySQL Error : Got error 'repetition-operator operand invalid' from regexp
    MySQL Errno : 1139
    Message : Got error 'repetition-operator operand invalid' from regexp
    Need Help?