程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 一種快速可預制的隨機數組產生方法

一種快速可預制的隨機數組產生方法

編輯:關於C++

本文介紹了一種簡單、快捷、實用的隨機數組產生方法,經調試通過。附件為全部程序代碼請審閱。

在工程軟件的設計和安全系統設計中,建立模型、產生密碼經常需要使用到隨機數組。然而計算機不會產生絕對隨機的隨機數,計算機只能產生“偽隨機數”。其實絕對隨機的隨機數只是一種理想的隨機數,即使計算機怎樣發展,它也不會產生一串絕對隨機的隨機數。計算機只能生成相對的隨機數,即偽隨機數。

偽隨機數並不是假隨機數,而是指有規律的數,事實上都是由計算機經過一定的算法計算得到的。大家常用的方法是根據一個給定的數作為種子,如采用變化的時間作為種子,調用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"改為你的隨機數池文件的位置," "中的空格數改為你所使用的空格數。

下面為本函數類中的主要函數代碼:

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環境中調試通過。

本方法所產生的隨機數組實質上是數池中相連的一組數,對於某一數組長度只能產生m_Txt_Line×m_Txt_Row個不同的隨機數組。因此越大的數池顯然效果越好。此外,我們可以采用另外一種更好的辦法撈取隨機數組。即首先用時間作為種子產生隨機數,從數池中撈取相應序號的數值,然後又用該數值作為種子生成隨機數,再從數池中撈取相應序號的數值。

如此循環下去,直至取夠需要的隨機數組。該方法的程序也很容易寫出,各位可以一試。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved