一种快速可预制的随机数组发生要领
副标题#e#
本文先容了一种简朴、快捷、实用的随机数组发生要领,经调试通过。附件为全部措施代码请审阅。
在工程软件的设计和安详系统设计中,成立模子、发生暗码常常需要利用到随机数组。然而计较机不会发生绝对随机的随机数,计较机只能发生“伪随机数”。其实绝对随机的随机数只是一种抱负的随机数,纵然计较机奈何成长,它也不会发生一串绝对随机的随机数。计较机只能生成相对的随机数,即伪随机数。
伪随机数并不是假随机数,而是指有纪律的数,事实上都是由计较机颠末必然的算法计较获得的。各人常用的要领是按照一个给定的数作为种子,如回收变革的时间作为种子,挪用srand((unsigned)time(NULL))后执行rand()从而得到一个随机数。很显然,沟通或临近的种子获得的随机数将会是完全一样或相互靠近。
因此要发生真正意义的随机数,那么种子首先必需是随机的。随机的种子可以通过外接的硬件随机产生器发生,听说最新的intel处理惩罚器即回收了读取cpu上热噪声的要领来获取随机数。当无法操作硬件的随机产生器时,我们常回收的步伐是,在两次挪用srand((unsigned)time(NULL))之间插手一按时间的延时。但当需要发生一个很大的随机数组时,这种延时是漫长而不行忍受的。并且事实上由于延时具有纪律性,发生的随机数也不那么随机。
一种容易想到的发生随机数组的要领是设计出巨大的算法,从而减小数组功效的纪律性。这种要领需要很高的能力,也不太适合一般措施的挪用。
另外,在许多环境下,我们不只要求发生随机的数组,同时还对发生的数组有统计纪律上的要求。如必需听从正态漫衍,匀称漫衍等。简朴的挪用srand和rand函数无法满意需要。
Matlab是一种成果强大的工程数学软件,操作其随机数组发生模块,我们能很容易的获得听从各类漫衍形式的大数组,其随机数发生的道理等于基于巨大的算法的。因此我们自然想到操作matlab发生的随机数表来作为随机数池,从中得到我们所需要的随机数组。
本随机数组发生要领由三部门构成:其一是txt文件的随机数池,这里我操作matlab发生1000个听从正态漫衍的随机数,10个一排,每两个数字之距离断3个空格,行首3个空格存为文本文档,第一个数序号为0,然后按先行后列序号依次分列到999;其二和三别离是从随机数池中捞取随机数的函数类的.h文件和.cpp文件。
在捞取随机函数的函数类中,界说CStdioFile的file1,打开作为随机数池的txt文档。首先以时间作为种子,发生一个0-999的随机数,读取随机数池中从以这个值为序号的开始的数,直到读够所需的随机数组。序号假如超出数池的范畴则跳到数池的开始,继承读取。
挪用本函数类,需要输入int m_Collect_Times,double *a_Random,int m_Txt_Line,int m_Txt_Row,int m_Txt_Spacing别离代表取点个数、取得的随机数组的存储位置、随机数池行数、列数、数池中两数间空格个数。并将"C:\\Yg\\Debug\\ramdom1000txt"改为你的随机数池文件的位置," "中的空格数改为你所利用的空格数。
#p#副标题#e#
下面为本函数类中的主要函数代码:
void CRandomArrayFromTxt::GetRandomArrayFromTxt(int m_Collect_Times,
double *a_Random,
int m_Txt_Line,
int m_Txt_Row,
int m_Txt_Spacing)
{
int m,mx,my,cl;
srand((unsigned)time(NULL)); // 生成时间种子
m=rand()%m_Txt_Line; // 返回一个0-m_Txt_Line-1的随机数,即查表的起始位置
mx=m%m_Txt_Row; // 查表起始位置的列号,文件头为0行0列
my=m/m_Txt_Row; // 查表起始位置的行号
cl=(m_Collect_Times+mx-1)/m_Txt_Row+1; // 需要从数表中读取的行数
// 打开txt文本的数表。
CStdioFile file1( "C:\\Yg\\Debug\\ramdom1000.txt",
CFile::modeNoTruncate | CFile::modeRead | CFile::typeText);
CString strc;
int ct=0; // 用于记录当前已经取得的随机数个数
for(m=0;m<my;m++)
{
file1.ReadString(strc);
}
// 取出有用的行,直到取够为之
for(int n=0;n<cl;n++)
{
if(n+my==m_Txt_Line)
file1.SeekToBegin();
// 数表不足长,从头定位到文件头
file1.ReadString(strc);
if(n==0) // 假如是取得的第一行
{
int aw1,aw2;
aw1=strc.GetLength();
for(m=0;m<mx+1;m++) // 过掉前面无用的空格
{
aw1=strc.GetLength();
aw2=strc.Find(" "); // 找到作为隔断的前三个空格地址位置
strc=strc.Right(aw1-aw2-m_Txt_Spacing); // 取这三个空格右边的所有字符串
}
// 下面取出剩下的字符串中每三个空格前面的字符串,就是所要查一个数据
for(m=0;m<m_Txt_Row-mx&&ct<m_Collect_Times;m++)
{
aw2=strc.Find(" ");// 找到作为隔断的后三个空格地址位置
if(mx==m_Txt_Row-1||m==m_Txt_Row-mx-1)
a_Random[ct]=atof(strc);
else
a_Random[ct]=atof(strc.Left(aw2)); // 生存数据到数组
aw1=strc.GetLength();
aw2=strc.Find(" "); // 找到作为隔断的前三个空格地址位置
strc=strc.Right(aw1-aw2-m_Txt_Spacing); // 取这三个空格右边的所有字符串
ct++;
}
}
else
{
GetRandomArrayFromALine(strc,a_Random,
m_Collect_Times,
m_Txt_Row,
m_Txt_Spacing,
ct);
ct+=m_Txt_Row;
}
}
file1.Close();
}
///////////////////////
// 从一行中取出数字
///////////////////////
void CRandomArrayFromTxt::GetRandomArrayFromALine(CString strc,
double *a_Random,
int m_Collect_Times,
int m_Txt_Row,
int m_Txt_Spacing,
int ct)
{
int aw1,aw2;
aw1=strc.GetLength();
aw2=strc.Find(" ");
strc=strc.Right(aw1-aw2-m_Txt_Spacing); // 取这三个空格右边的所有字符串
for(int m=0;m<m_Txt_Row&&ct<m_Collect_Times;m++)
{
aw2=strc.Find(" ");
if(m==m_Txt_Row-1)
a_Random[ct]=atof(strc);
else
a_Random[ct]=atof(strc.Left(aw2));// 生存数据到数组
aw1=strc.GetLength();
aw2=strc.Find(" ");// 找到作为隔断的前三个空格地址位置
strc=strc.Right(aw1-aw2-m_Txt_Spacing); // 取这三个空格右边的所有字符串
ct++;
}
}
本工程在VC++5.0、WindowsXP情况中调试通过。
#p#分页标题#e#
本要领所发生的随机数组实质上是数池中相连的一组数,对付某一数组长度只能发生m_Txt_Line×m_Txt_Row个差异的随机数组。因此越大的数池显然结果越好。另外,我们可以回收别的一种更好的步伐捞取随机数组。即首先用时间作为种子发生随机数,从数池中捞取相应序号的数值,然后又用该数值作为种子生成随机数,再从数池中捞取相应序号的数值。
如此轮回下去,直至取够需要的随机数组。该要领的措施也很容易写出,列位可以一试。
本文配套源码