有时我们使用for循环去产生随机数组时,发现其生成的随机数都一样,这和我们想要的不一样。通过查阅相关资料后发现,是因为当计算机的性能较快时,for循环运行时间非常短,srand(time(NULL))每次都返回相同的值。
原因:用系统时间做随机种子并不保险,如果应用程序在一个较快的计算机上运行,则该计算机的系统时钟可能没有时间在此构造函数的调用之间进行更改,Random 的不同实例的种子值。
解决方法一:使用Random ra=new Random();
解决方法二:使用Sleep()函数。
Sleep函数
功能: 执行挂起一段时间,也就是等待一段时间在继续执行
用法: Sleep(时间)
头文件: Windows下为--> windows.h
Linux 下为 --> unistd.h
注意: (1)Sleep是区分大小写的,有的编译器是大写,有的是小写。
在windows下是已毫秒为单位,而Linux是以秒为单位
代码实例:
首先贴出没有使用Sleep函数时的代码和结果:
/**
******************************************************
*
* @note 产生lamda的泊松分布
*
* @data 2020-07-26-20:00
*
* @copyright Mr.zhi
*
******************************************************
*/
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iomanip>
// Sleep()函数的头文件
#include <windows.h>
using namespace std;
//产生一(a,b)的均匀分布
double U_Randa(double a, double b)
{
double x = rand();
return a+(b-a)*(x+1)/(RAND_MAX+1);
}
//泊松分布,Lamda为唯一的一个参数,均值和方差
double Possion(double Lamda)
{
double u;
int x = -1;
double log1, log2;
log1 = 0;
log2 = -Lamda;
srand(time(NULL));
do
{
u = U_Randa(0,1);
// cout << "u = " << u << endl;
log1 += log(u);
x++;
}while(log1 >= log2);
return x > 0 ? x : 0;
}
int main() {
double k[10];
for(int i=0;i<10;i++){
k[i] = Possion(2);
cout << "k[" << i << "] = " << k[i] << endl;
}
}
运行结果:
可以发现,此时即使使用系统时间做随机种子,产生的随机数仍然是一样的。因此for循环从运行时间很快,导致srand(time(NULL))的返回值相同。下面使用Sleep函数时的代码和运行结果(因为和上面的代码总体一样,这里只对主函数进行展示):
int main() {
double k[10];
int S_time = 1000;
cout << "Sleep time = " << S_time << "ms" << endl;
for(int i=0;i<10;i++){
/*因为for循环时间很快,这里使用Sleep函数对进程休眠1000ms。
*如果Sleep()休眠时间较短,则仍会产生一部分重复的值*/
Sleep(1000);
k[i] = Possion(2);
cout << "k[" << i << "] = " << k[i] << endl;
}
}
运行结果为:
可以发现,使用Sleep()函数后,产生的伪随机数不再相同。
这里,如果Sleep()的时间较短,则仍会产生部分重复的值。如当Sleep(100)时,结果如下:
虽然使用Sleep()函数可以简单的克服srand(time(NULL))不准确的缺点,但是该方法的有着一个重要的缺陷就是当for循环较大时,会占用很大的时间,导致代码运行时间很大。
这里先对Sleep()函数进行介绍,其余的方法等有时间了再做补充!
此笔记只是用来记录自己平时遇到的问题,解决方法和代码可能有不准确的地方,如有错误请指出或者忽略,谢谢。