• C/C++生成随机数


    一、rand和srand

      在C++11标准出来之前,C/C++都依赖于stdlib.h头文件的rand或者srand来生成随机数。

      其不是真正的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统。

    • rand:内部是线性同余实现的,因为周期较长,所以在一定的范围内可看成随机的。系统默认随机种子是1。rand()返回一随机数值的范围在0至RAND_MAX 间。RAND_MAX的范围最少是在32767之间(int)。用unsigned int 双字节是65535,四字节是4294967295的整数范围。0~RAND_MAX每个数字被选中的机率是相同的。
    //函数声明
    int rand(void);
    
    • srand:srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。
    //函数声明
    void srand(unsigned int seed);
    
    • 常见用法如下:

      • (rand() % (b - a)) + a ,生成[a, b) 的随机整数
      • (rand() % (b - a + 1)) + a ,生成[a,b] 的随机整数
      • rand() / double(RAND_MAX) ,生成0~1之间的浮点数
    • 来个测试代码:

    #include <iostream> 
    #include <stdlib.h> 
    #include <time.h>  
    using namespace std;  
    int main() 
    {  
        srand((unsigned)time(NULL));  
        for(int i = 0; i < 10;i++ )  
            cout << rand() << '	';  
        cout << endl;  
        return 0; 
    }
    

    二、新标准随机数

      有时候程序员需要一些非均匀分布的数,这时候rand就显得不是那么好用,新标准很好解决了这个问题:随机数引擎类随机数分布类。引擎用来生成随机unsigned整数序列,分布则使用引擎返回服从特定概率分布的随机数。

      标准库定义了多个随机数引擎类,区别在于性能和随机性质量不同。每个编译器都会指定其中一个作为default_random_engine类型。标准库定义的引擎通用操作如下:

    操作 解释
    Engine e 默认构造函数,使用该引擎默认的种子
    Engine e(s) 使用整型值s作为种子
    e.seed(s) 使用种子s重置引擎的状态
    e.max(), e.min() 该引擎可生成的最大和最小值
    Engine::result_type 该引擎生成的unsigned整型类型
    e.discard(u) 将引擎推进u步,u为unsigned long long类型

      对于大多数场合,随机数引擎的输出是不能直接使用的,还要配合合适的分布类。均匀分布类为uniform_int_distribution<unsigned>。标准库中的分布类的通用操作如下:

    操作 解释
    Dist d 默认构造函数
    d(e) 用相同的引擎e连续生成随机数序列
    d.max(), d.min() 返回d(e)能生成的最大和最小值
    d.reset() 重建d的状态,使得随后对d的使用不依赖于d已经生成的值

      以下为简单测试:

    #include <iostream>
    #include <random>
    
    using namespace std;
    
    int main() {
        //0~9的均匀分布
    	uniform_int_distribution<unsigned> u(0,9);
    	//若想生成0~1的double
    	//uniform_int_distribution<double> u(0,1);
    	default_random_engine e;
    	for(size_t i = 0; i < 10; i++)
    		cout << u(e) << " ";
    	//由于是默认的种子,所以应该都是0 1 7 4 5 2 0 6 6 9
    	return 0;
    }
    

      为了生成不同的结果,我们可以通过设置种子,为引擎设置种子的方法有两种方式:在创建引擎对象的时候提供种子,或者调用引擎的seed成员。简单测试如下:

    #include <iostream>
    #include <random>
    
    using namespace std;
    
    int main() {
    	default_random_engine e1; //默认种子
    	default_random_engine e2(2147483646); //给定的种子
    	default_random_engine e3;
    	e3.seed(32767); //调用成员seed
    	default_random_engine e4(32767); //和e3一样的种子
    	uniform_int_distribution<unsigned> u(0,9);
    	for(size_t i = 0; i < 10; i++)
    		cout << u(e1) << " " << u(e2) << " " << u(e3) << " " << u(e4) << endl;
    	return 0;
    }
    

      除了均匀分布下生成unsined整数,我们还可以生成不同分布下别的类型的数值。比如uniform_real_distribution<> u(0,1)生成0~1的double类型值,还有normal_distribution<> n(4,1.5)生成均值为4,标准差为1.5的正态分布double类型值。

    实际上,新标准定义了20种分布类型,如有需要,请翻阅C++11文档。

  • 相关阅读:
    界面控件DevExpress ASP.NET Controls v21.2 甘特图性能增强
    New!DevExpress ASP.NET v21.2最新版本系统环境配置要求
    界面控件DevExpress WinForm MVVM命令讲解(一)
    界面控件DevExpress WPF入门级教程 触摸滚动条
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 1)
    WinForm应用界面美化攻略 MVVM 高级绑定功能
    Telerik UI组件官宣支持.NET 6 和 VS 2022,让现代UI变得更简单
    界面控件Telerik UI for WinForm初级教程 版本升级
    界面控件DevExpress WPF入门指南 表达式 & 表达式编辑器
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 2)
  • 原文地址:https://www.cnblogs.com/vachester/p/7604292.html
Copyright © 2020-2023  润新知