C++11 随机数生成
C++ 程序中,在新标准出现之前,C 和 C++ 都依赖一个C 库函数 rand 来产生随机数,然而,这个函数生成的是均匀分布的伪随机数,每个随机数的范围在 0 和一个最大值RAND_MAX(至少为 32767)之间。
rand 函数存在一些问题:在实际的编程中,很多程序需要不通范围的随机数。一些应用需要随机浮点数。一些程序需要非均匀分布的随机数。所在在编写程序时为了生成满足一定要求的随机数,通常会转换 rand 生成的随机数的范围、类型或者是分布,但是这样会引入非随机性。
c++11提供的<random>实现了随机数库,它通过随机数引擎类(random_number_engines)产生随机数序列,随机数分布类(random_number_distribution)使用随机数引擎生成服从特定概率分布的随机数。
下面介绍一个C++中生成随机数的例子:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> //#include "Timer.h" #include <random> // const int arraySize = 100000; int main() { std::default_random_engine e; // 默认的随机数引擎 for (int i = 0; i < 15; i++) { auto rnd = e(); std::cout << rnd << std::endl; std::cout << typeid(rnd).name() << std::endl; // 返回值的类型 } std::cout << e.max() << " | " << e.min() << std::endl; // 随机数引擎的范围 //system("pause"); return 0; }
随机数类是定义在std命名空间的,所以要声明。随机数引擎是函数对象,这就是为什么使用e()去生成随机数。程序每次运行都会生成相同的随机数序列,这在一定程度有利于程序的调试,但我们有时需要每一次运行产生的随机数序列都是不同的。我们可以通过设置随机数引擎的种子来改变引擎的状态,没有改变时是使用默认的随机数种子,这就是为什么每一次都生成同样的随机数序列。从结果我们可以知道,默认的种子生成随机数范围在1-2147483646之间。
可以通过e.seed()方法来设置随机数种子:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> //#include "Timer.h" #include <random> // const int arraySize = 100000; int main() { std::default_random_engine e; // 默认的随机数引擎 e.seed(10); // 设置生成随机数的种子 for (int i = 0; i < 15; i++) { auto rnd = e(); std::cout << rnd << std::endl; //std::cout << typeid(rnd).name() << std::endl; // 返回值的类型 } std::cout << e.max() << " | " << e.min() << std::endl; // 随机数引擎的范围 //system("pause"); return 0; }
如果需要改变生成的随机数的范围,需要使用随机数分布类:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> //#include "Timer.h" #include <random> // const int arraySize = 100000; int main() { std::default_random_engine e; // 默认的随机数引擎 std::uniform_int_distribution<int> u(0, 10); // 随机数分布类,可以确定随机数范围 [0,10] e.seed(10); // 设置生成随机数的种子 for (int i = 0; i < 15; i++) { auto rnd = u(e); std::cout << rnd << " "; //std::cout << typeid(rnd).name() << std::endl; // 返回值的类型 } std::cout << std::endl; std::cout << e.max() << " | " << e.min() << std::endl; // 随机数引擎的范围 //system("pause"); return 0; }
在实际的应用中,[0, 1]之间的随机数应用的比较广泛,在C++11中,可以按照如下的方式生成满足要求的随机数:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> //#include "Timer.h" #include <random> // const int arraySize = 100000; int main() { std::default_random_engine e; // 默认的随机数引擎 std::uniform_real_distribution<double> u(0, 1); // 随机数分布类,可以确定随机数范围 [0,10] e.seed(10); // 设置生成随机数的种子 for (int i = 0; i < 15; i++) { auto rnd = u(e); std::cout << rnd << " "; //std::cout << typeid(rnd).name() << std::endl; // 返回值的类型 } std::cout << std::endl; std::cout << e.max() << " | " << e.min() << std::endl; // 随机数引擎的范围 //system("pause"); return 0; }
除此之外,c++11的<random>库还提供了不同的随机数引擎和随机数分布类,例如,要生成满足正态分布的0-1之间的随机数:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> #include "Timer.h" #include <random> // const int arraySize = 100000; int main() { std::default_random_engine e; // 默认的随机数引擎 // std::normal_distribution的构造函数 可知参数的意义 // explicit normal_distribution(_Ty _Mean0 = 0.0, _Ty _Sigma0 = 1.0) std::normal_distribution<double> u(0, 1); // 正态分布 e.seed(10); // 设置生成随机数的种子 for (int i = 0; i < 15; i++) { auto rnd = u(e); std::cout << rnd << " "; //std::cout << typeid(rnd).name() << std::endl; // 返回值的类型 } std::cout << std::endl; std::cout << e.max() << " | " << e.min() << std::endl; // 随机数引擎的范围 //system("pause"); return 0; }
C++11 提供的随机数引擎和随机数分布类型如下所示:
http://www.cplusplus.com/reference/random/?kw=random
随机数引擎:
随机数分布类:
------------------------------------------------------------------------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)