使用STL生成随机数

Monday, June 15, 2020

随机数种子

使用随机数引擎生成(伪)随机数前,我们通常需要传入一个种子以确保程序每次运行能生成不同的随机数

random_device 类可以使用系统提供的数据源,并返回一个真随机数(根据实现,如果数据源不可用也可能生成伪随机数),取值范围是[std::random_device::min() , std::random_device::max()]

#include <iostream>
#include <random>

using namespace std;

int main()
{
    cout << "Max: " << std::random_device::max() <<endl;
    cout << "Min: " << std::random_device::min() <<endl;

    random_device rd;
    for (int n = 0; n < 8; ++n) {
        cout << rd() << endl;
    }
}

输出:

Max: 4294967295
Min: 0
2767121154
1691292331
801934702
482676768
4189593090
213760575
301031565
973228337

为什么不直接使用random_device生成的随机数

生成一个真随机数会急剧消耗系统采集的熵,采集速度远远不及实际的使用速度,熵小了,生成的数就不那么随机了

随机数引擎

使用默认随机数引擎

#include <iostream>
#include <random>

using namespace std;

int main()
{
    cout << "Max: " << std::default_random_engine::max() <<endl;
    cout << "Min: " << std::default_random_engine::min() <<endl;

    random_device rd;
    default_random_engine e(rd());
    for (int n = 0; n < 8; ++n) {
        cout << e() << endl;
    }
}

输出:

Max: 2147483646
Min: 1
1723848096
1013067795
1380077149
2133255643
1388105236
1769844091
973642840
189821740

其他引擎可以参看参考手册https://devdocs.io/cpp/header/random

使用分布类

有时候我们可能对随机数有额外要求,比如取值范围,比如负数,比如浮点数……

当然我们可以自己对引擎生成的随机数做额外处理,但更简单可靠的方法是使用STL的分布类

离散均匀分布

#include <iostream>
#include <random>

using namespace std;

int main()
{
    random_device rd;
    default_random_engine e(rd());
    uniform_int_distribution<> dist(-5, 5); //返回值范围为[-5, 5]
    for (int n = 0; n < 8; ++n) {
        cout << dist(e) << " ";
    }
}

输出:

5 -1 -1 3 5 -4 4 -5 

连续均匀分布

#include <iostream>
#include <random>

using namespace std;

int main()
{
    random_device rd;
    default_random_engine e(rd());
    //返回值范围为[0, 214)
    uniform_real_distribution<> dist(0.0, 214.0); 
    for (int n = 0; n < 8; ++n) {
        cout << dist(e) << " ";
    }
}

输出:

68.0202 10.1525 17.0463 142.749 40.447 57.8053 58.8224 153.853 

STL中还有正态分布,泊松分布等,我平常用的比较少不再赘述


参考:

cpp

Div+CSS实现文本居中左对齐

c++中++i和i++的区别