c++11提供的<random>实现了随机数库,它通过随机数引擎类(random_number_engines)产生随机数序列,随机数分布类(random-number distribution)使用随机数引擎生成服从特定概率分布的随机数。
让我们看一个简单的例子:
#include <iostream>
#include <random>
using std::cout; using std::endl;
using std::default_random_engine;
int main()
{
default_random_engine e;
for (size_t i = 0; i < 10; ++i) //生成十个随机数
cout << e() << endl;
cout << "Min random:" << e.min() << endl; //输出该随机数引擎序列的范围
cout << "Max random:" << e.max() << endl;
return 0;
}
生成的随机数结果:
在例子中,随机数类是定义在std命名空间的,所以要声明。随机数引擎是函数对象,这就是为什么使用e()去生成随机数。程序每次运行都会生成相同的随机数序列,这在一定程度有利于程序的调试,但我们有时需要每一次运行产生的随机数序列都是不同的。我们可以通过设置随机数引擎的种子来改变引擎的状态,没有改变时是使用默认的随机数种子,这就是为什么每一次都生成同样的随机数序列。从结果我们可以知道,默认的种子生成随机数范围在1-2147483646之间。
#include <iostream> #include <random> using std::cout; using std::endl; using std::default_random_engine; int main() { default_random_engine e; //或者直接在这里改变种子 e(10) e.seed(10); //设置新的种子 for (size_t i = 0; i < 10; ++i) cout << e() << endl; cout << "Min random:" << e.min() << endl; cout << "Max random:" << e.max() << endl; return 0; }
设置新的种子后结果如下:
在结果可以看出,生成随机数序列不同了。在这里范围还是一样的,那么怎么去改变生成的范围呢?这时就可以使用随机数分布类了。
#include <iostream> #include <random> using std::cout; using std::endl; using std::default_random_engine; using std::uniform_int_distribution; int main() { default_random_engine e; uniform_int_distribution<unsigned> u(0, 9); //随机数分布对象 for (size_t i = 0; i < 10; ++i) //生成范围为0-9的随机数序列 cout << u(e) << " "; cout << endl; return 0; }
结果如下:
这里要注意的这个序列也是每次运行程序相同的,因为分布对象将随机数引擎作为它的参数,分布对象使用它的引擎参数生成随机数,并将其映射到指定的分布。
---------------------------------------------------------------------------------------------------------------------------------------
现在,让我更深入一点吧,在图形上很多时候都要使用0.0-1.0的值(颜色)作为数据,那么怎么生成这样的序列呢?跟刚才那样,我们可以使用分布区定义范围。
#include <iostream> #include <random> using std::cout; using std::endl; using std::default_random_engine; using std::uniform_real_distribution; int main() { default_random_engine e; uniform_real_distribution<double> u(0, 1); //随机数分布对象 for (size_t i = 0; i < 5; ++i) //生成范围为0.0-1.0的随机数序列 cout << u(e) << " "; cout << endl; return 0; }
结果:
在这里分布类改变了类型,采用的是real实数类型的分布类,实例化为<double>,生成0.0-1.0的double随机数序列。如果你想要获得分布类范围的端点,只要简单的成员函数min()和max()就可以了。
随机数的重要性质是随机分布,但是我们也可以生产非均匀分布的随机数序列。
下面的例子生成符合正态分布的随机数序列:
#include <iostream> #include <random> #include <vector> #include <string> using std::cout; using std::endl; using std::default_random_engine; using std::normal_distribution; using std::vector; using std::string; int main() { default_random_engine e; vector<unsigned> vals(9); normal_distribution<> n(4, 1.5); //正态分布,大部分生成的随机数落在0-8之间 for (size_t i = 0; i != 200; ++i) { unsigned v = lround(n(e)); //舍入到最近整数 if (v < vals.size()) ++vals[v]; //统计0-8数字出现的次数 } for (decltype(vals.size()) i = 0; i != vals.size(); ++i) cout << i << ": " << string(vals[i], ‘#‘) << endl; return 0; }
结果:
更多资料可看:C++Primer 5th
或者 :http://www.cplusplus.com/reference/random/?kw=random