C++ 实现随机数生成(WindowsLinux)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 实现随机数生成(WindowsLinux)相关的知识,希望对你有一定的参考价值。

1、简介

伪随机数是用确定性的算法计算出来自[0,1]均匀分布的随机数序列。并不真正的随机,但具有类似于随机数的统计特征,如均匀性、独立性等。在计算伪随机数时,若使用的初值(种子)不变,那么伪随机数的数序也不变。

伪随机数可以用计算机大量生成,在模拟研究中为了提高模拟效率,一般采用伪随机数代替真正的随机数。模拟中使用的一般是循环周期极长并能通过随机数检验的伪随机数,以保证计算结果的随机性。

2、windows随机数

2.1 随机数范围计算公式

产生一定范围随机数的通用表示公式是:

要取得[0,n)  就是rand()%n     表示 从0到n-1的数
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 
要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。 
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。

2.2 rand()

rand()会返回一随机数值, 范围在0至RAND_MAX 间。RAND_MAX定义在stdlib.h, 其值为2147483647。

#include <iostream>
#include <cstdlib>
using namespace std;

int main()

    for (int i = 0; i < 10000; i++)
    
        cout << rand()%100<< " ";
    
    return 0;

2.3 srand()

srand()可用来设置rand()产生随机数时的随机数种子。通过设置不同的种子,我们可以获取不同的随机数序列。可以利用srand((int)(time(NULL))的方法,利用系统时钟,产生不同的随机数种子。不过要调用time(),需要加入头文件< ctime >。

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()

    srand((int)time(0));  // 产生随机种子  把0换成NULL也可以
    for (int i = 0; i < 10000; i++)
    
        cout << rand()%100<< " ";
    
    return 0;

#include <cstdlib>
#include <ctime>
using namespace std;
int main() 

    srand(time(nullptr)); // 用当前时间作为种子
    int min = 5, max = 10;
    int randomValue = (rand() % (max - min)) + min;//范围[min,max)
    randomValue = (rand() % (max - min + 1)) + min;//范围[min,max]
    randomValue = (rand() % (max - min)) + min + 1;//范围(min,max]

2.4 c++11 <random>

https://en.cppreference.com/w/cpp/numeric/random

C++标准建议使用<random>代替rand()。 <random>(since C++11) <random>中定义了随机数生成引擎、随机数分布律、不确定随机数和预定义的最佳算法实践。

2.4.1 随机数生成引擎

<random>提供了三种引擎,使用哪种需要权衡:

  • linear_congruential_engine(线性同余随机数引擎):速度比较快,储存很少的中间变量。
  • mersenne_twister_engine(梅森旋转随机数引擎):比较慢,占用存储空间较大,但是在参数设置合理的情况下,可生成最长的不重复序列,且具有良好的频谱特征。
  • subtract_with_carry_engine(带进位随机数引擎):速度最快,占用存储空间较大,频谱特性有时不佳。

上面的三种随机数生成算法均是模板类,需要我们自己进行实例化;模板类实例化需要的参数,均是算法中使用的参数,若是不懂其原理,建议不要使用这些模板类。不过不用担心,在C++11标准中,已经帮我们预先定义了一些随机数类(预定义算法),它们都是用过上面的三个类模板实例化出来的。

2.4.2 随机数分布律

可以预先定义随机数分布的概率分布,如正态分布uniform_int_distribution、伯努利分布binomial_distribution、泊松分布poisson_distribution等等。

2.4.3 预定义算法

定义了算法的最佳实践,避免了参数的选择,可以直接选择引擎,设定分布规律就好。算法包括minstd_rand0、minstd_rand、mt19937、mt19937_64、ranlux24_base、ranlux48_base等。

类名称 属性 依赖类
linear_congruential_engine templates \\
mersenne_twister_engine templates \\
subtract_with_carry_engine templates \\
discard_block_engine Engine adaptors \\
independent_bits_engine Engine adaptors \\
shuffle_order_engine Engine adaptors \\
default_random_engine instantiations 待定
minstd_rand instantiations linear_congruential_engine
minstd_rand0 instantiations linear_congruential_engine
mt19937 instantiations mersenne_twister_engine
mt19937_64 instantiations mersenne_twister_engine
ranlux24_base instantiations subtract_with_carry_engine
ranlux48_base instantiations subtract_with_carry_engine
ranlux24 instantiations ranlux24_base、discard_block_engine
ranlux48 instantiations ranlux48_base、discard_block_engine
knuth_b instantiations shuffle_order_engine

2.4.4 random_device

random_device是标准库提供的一个非确定性随机数生成设备,是所有生成器中唯一一个不需要随机数种子的方式。在Linux中,是需要读取/dev/urandom设备。需要注意的是random_device在某些操作系统中是无法使用的,会在构造函数或者调用operator()函数时抛出异常,因此在进行代码移植时,需要格外注意。

2.4.5 实现代码

#include <random>
using namespace std;

int main()
  int min = 0,max = 100;
  random_device seed;//硬件生成随机数种子
  ranlux48 engine(seed());//利用种子生成随机数引擎
  uniform_int_distribution<> distrib(min, max);//设置随机数范围,并为均匀分布
  int random = distrib(engine);//随机数

#include <iostream>
#include <random>

int main(int argc, char**argv)
	std::default_random_engine engine;
    for (int i = 0; i < 10; ++i )
        std::cout << engine() << " ";
    
    std::cout << std::endl;
	return 0;


3、linux随机数

3.1 简介

/dev/random 和 /dev/urandom /dev/urandom 是一个伪随机数生成器,缺乏熵它也不会停止。 /dev/random 是一个真随机数生成器,它会在缺乏熵的时候停止。

3.4.3 std::random_device

C++ 中也提供了真随机数 random_device。它在 Windows 下调用 rand_s,在 Linux 下调用 /dev/urandom。真随机数的优点是足够随机,但它会消耗很多系统资源,在某些情况下是不可接受的。在真随机数的生成里,把随机数的生成分成两个部分,第一个部分称之为熵生成,指的就是前面说的各类噪声,第二部分就是熵提取,指的就是把噪声数据进行变化。

#include <iostream>
#include <random>
double getRandomDevice()

	std::random_device rd;
	std::mt19937 mt(rd());
	return (unsigned int)mt();

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭ 如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O??? 如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡) 感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

以上是关于C++ 实现随机数生成(WindowsLinux)的主要内容,如果未能解决你的问题,请参考以下文章

C++生成随机数

C++中随机数生成范围内

c++中产生不重复的随机数

C++实现邮件群发的方法

C++:随机数生成

C++ 生成随机数