C++生成随机数的实现代码

 更新时间:2020年04月19日 09:14:05   作者:jerry_fuyi  
这篇文章主要介绍了C++生成随机数的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

C风格

C为随机数提供的工具是rand、srand和RAND_MAX,定义在<stdlib.h>中。

srand为rand设置种子,如果不设置,相当于调用过srand(1)。rand产生伪随机数,其范围为0到RAND_MAX,RAND_MAX至少是32767,在MSVC和GCC中这个值都是32767。

伪随机数看似随机,实则是有规律可循的,对于相同的种子值,rand产生的序列完全相同,也就是说无论你给srand一个什么数字,多次运行程序的结果都将相同——除非你给srand的是不同的数字,比如时间。<time.h>中的time函数返回整数表示的系统时间,可用于设置种子。

如果我们只需要0到9的随机数,可以把rand的返回值% 10;如果是42到233,可以写rand() % 192 + 42。下面的random函数封装了这项工作。注意只有在b - a + 1远小于或整除RAND_MAX时随机数的分布才比较均匀。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int random(int a, int b)
{
  return rand() % (b - a + 1) + a;
}

int main()
{
  srand(time(NULL));
  printf("RAND_MAX = %d\n", RAND_MAX);
  for (int i = 0; i < 10; i++)
    printf("%d ", rand());
  printf("\n");
  int count[10] = {0};
  for (int i = 0; i < 10000; i++)
    count[random(0, 9)]++;
  for (int i = 0; i < 10; i++)
  {
    printf("%d: ", i);
    for (int j = 0; j < count[i] / 10; j++)
      printf("*");
    printf("\n");
  }
}

C++风格

从C++11开始,C++标准规定了随机数设施,包括均匀随机位生成器(Uniform random bit generators,URBG)和随机数分布等,定义在<random>中。

URBG分为随机数引擎、引擎适配器、预置随机数生成器和非确定随机数生成器4类,通常后两类就够用了。

标准规定了3种随机数引擎:

  • 线性同余linear_congruential_engine(LCG),时间空间消耗都少;
  • 梅森旋转mersenne_twister_engine(MT),占用较多内存(在PC上可以忽略),计算量较大;
  • 带进位减法(属于滞后斐波那契生成器,LFG)subtract_with_carry_engine,性能与效果折中。

随机数引擎都需要一个种子,生成的都是伪随机数。

引擎适配器可以套一个随机数引擎:

  • discard_block_engine在连续若干个伪随机数中选择若干个;
  • independent_bits_engine把位数多的伪随机数压缩成位数少的;
  • shuffle_order_engine把连续若干个伪随机数重排。

套娃的方式是模板,理论上你还可以用适配器套适配器,不过CPU可能会有意见。

随机数引擎的模板参数怎么取?标准定义了一些数学家们发现的效果良好的随机数引擎:LCG minstd_rand0、minstd_rand、knuth_b;MT mt19937、mt19937_64;LFG ranlux24_base、ranlux48_base、ranlux24、ranlux48。如果你还是无从下手,那就用default_random_engine,编译器的开发者们为你选好了他们认为最合适的,在MSVC中是mt19937,在GCC中是minstd_rand0。

以上工具都生成伪随机数,标准还定义了真·随机数引擎random_device,尽管标准也允许它是伪随机的。如果它是真随机的,那么使用起来它的效果无疑是最好的,但是多次调用后性能会急剧下降,通常只用于生成伪随机数引擎的种子。

随机数生成器类型都定义了静态方法min和max,返回生成的随机数的范围,以及无参数的函数调用运算符operator(),返回随机数。

#include <iostream>
#include <random>

int main()
{
  auto engine = std::default_random_engine(std::random_device()());
  std::cout << "min = " << engine.min() << "; max = " << engine.max() << std::endl;
  std::cout << "random numbers: ";
  for (int i = 0; i != 10; ++i)
    std::cout << engine() << ' ';
  std::cout << std::endl;
}

大多数情况下我们不需要min到max范围的整数,而需要一定分布的整数或实数。标准规定了许多随机数分布类型,我数学不好,不太懂这些。

  • 均匀分布uniform_int_distribution、uniform_real_distribution;
  • 伯努利分布bernoulli_distribution、binomial_distribution、negative_binomial_distribution、geometric_distribution;
  • 泊松分布poisson_distribution、exponential_distribution、gamma_distribution、weibull_distribution、extreme_value_distribution;
  • 正态分布normal_distribution、lognormal_distribution、chi_squared_distribution、cauchy_distribution、fisher_f_distribution、student_t_distribution;

抽样分布discrete_distribution、piecewise_constant_distribution、piecewise_linear_distribution。

构造分布实例时传入分布的参数。调用operator()获得结果,参数为随机数引擎。

#include <iostream>
#include <random>
#include <string>

int main()
{
  auto engine = std::default_random_engine(std::random_device()());
  std::uniform_int_distribution<int> uniform(0, 9);
  int count[10] = {0};
  for (int i = 0; i != 10000; ++i)
    ++count[uniform(engine)];
  for (int i = 0; i != 10; ++i)
    std::cout << i << ": " << std::string(count[i] / 10, '*') << std::endl;
}

注意,与STL中左闭右开的习惯不同,uniform_int_distribution构造函数接受的参数是闭区间。

到此这篇关于C++生成随机数的实现代码的文章就介绍到这了,更多相关C++生成随机数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言例题讲解指针与数组

    C语言例题讲解指针与数组

    在C语言和C++等语言中,数组元素全为指针变量的数组称为指针数组,指针数组中的元素都必须具有相同的存储类型、指向相同数据类型的指针变量。指针数组比较适合用来指向若干个字符串,使字符串处理更加方便、灵活
    2022-07-07
  • C++学习之移动语义与智能指针详解

    C++学习之移动语义与智能指针详解

    智能指针和移动语义是迄今为止,最难理解的两个概念,下面这篇文章主要给大家介绍了关于C++学习之移动语义与智能指针的相关资料,需要的朋友可以参考下
    2021-05-05
  • OpenCV使用稀疏光流实现视频对象跟踪的方法详解

    OpenCV使用稀疏光流实现视频对象跟踪的方法详解

    这篇文章主要为大家详细介绍了OpenCV如何使用稀疏光流实现视频对象跟踪功能,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2023-02-02
  • C++友元函数与拷贝构造函数详解

    C++友元函数与拷贝构造函数详解

    这篇文章主要介绍了C++友元函数与拷贝构造函数,需要的朋友可以参考下
    2014-07-07
  • C++实现坦克大战小游戏EGE图形界面

    C++实现坦克大战小游戏EGE图形界面

    这篇文章主要为大家详细介绍了C++实现坦克大战小游戏EGE图形界面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 离线安装visual studio2022+QT5.12的实现步骤

    离线安装visual studio2022+QT5.12的实现步骤

    近期有需求离线配置C++与QT环境,本文主要介绍了离线安装visualstudio2022+QT5.12的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • C语言数据结构实现链表逆序并输出

    C语言数据结构实现链表逆序并输出

    这篇文章主要介绍了C语言数据结构实现链表逆序并输出的相关资料,需要的朋友可以参考下
    2017-04-04
  • 如何在C语言中提取Shellcode并执行

    如何在C语言中提取Shellcode并执行

    Shellcode是一种独立于应用程序的机器代码,通常用于实现特定任务,如执行远程命令、注入恶意软件或利用系统漏洞,本文将深入探讨如何在C语言中提取Shellcode,并通过XOR加密技术增加其混淆程度,文中通过代码示例讲解的非常详细,需要的朋友可以参考下
    2023-12-12
  • 在clion上配置libtorch开发环境的图文详解

    在clion上配置libtorch开发环境的图文详解

    这篇文章主要介绍了在clion上配置libtorch开发环境的图文详解,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • C++抽象基类讲解

    C++抽象基类讲解

    这篇文章主要介绍了C++抽象基类讲解,象基类abstract base class简称ABC,C++实现继承的时候,需要保证派生类和基类之间是一种is-a的关系。在大多数时刻,这样的关系是没有问题的,然而在一些特殊的情况可能会遇到问题,下面来看看文章的具体介绍吧
    2022-01-01

最新评论