程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 詳解C說話的隨機數生成及其相干標題

詳解C說話的隨機數生成及其相干標題

編輯:關於C++

詳解C說話的隨機數生成及其相干標題。本站提示廣大學習愛好者:(詳解C說話的隨機數生成及其相干標題)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C說話的隨機數生成及其相干標題正文


發生隨機數的根本辦法

本文中,筆者將引見c說話所供給的隨機數產生器的用法。如今的c編譯法式都供給了一個基於一種ANSI尺度的偽隨機數產生器函數,用來生成隨機數。Microsoft和Borland都是經由過程rand()和srand()函數來支撐這類尺度的,它們的任務進程以下:
起首,給srand()供給一個“種子”,它是一個unsignde int類型,其取值規模是從0到65,535 ;
然後,挪用rand(),它會依據供給給srand()的“種子”值前往一個隨機數(在0到32,767之間);
依據須要屢次挪用rand(),從而赓續地獲得新的隨機數;
不管甚麼時刻,你都可以給srand()供給一個新的“種子”,從而進一步“隨機化"rand()的輸入成果。

這個進程看起來很簡略,成績是假如你每次挪用srand()時都供給雷同的“種子”值,那末你將會獲得雷同的“隨機”數序列。例如,在以17為“種子”值挪用srand()以後,在你初次挪用rand()時,你將獲得隨機數94;在你第二次和第三次挪用rand()時,你將分離獲得26,602和30,017。這些數看上去是相當隨機的(雖然這只是一個很小的數據點聚集),然則,在你再次以17為“種子”值挪用srand()以後,在對rand()的前三次挪用中,所獲得的前往值依然是94、26,602和30,017,而且爾後獲得的前往值依然是在對rand()的第一批挪用中所獲得的其他的前往值。是以,只要再次給srand()供給一個隨機的“種子”值,能力再次獲得一個隨機數。

上面的例子用一種簡略而有用的方法來發生一個相當隨機的“種子”值——當天的時光值。

# include <stdlib. h>
# include <stdio. h>
# include <sys/types. h>
# include <sys/timeb. h>
void main (void){
  int i ;
  unsigned int seedVal;
  struct_timeb timeBuf ;
  _ftime (&timeBuf) ;
  seedVal = ( ( ( ( (unsigned int)timeBuf, time & 0xFFFF) +
          (unsigned int)timeBuf, millitm) ^
          (unsigned int)timeBuf, millitm) ;
  srand ((unsigned int)seedVal) ;
  for(i=O;i<lO;++i)
    printf (" %6d\n" ,rand ( ) ) ;
}

上例先是挪用_ftime()來檢索以後時光,並把它的值存入構造成員timeBuf.time中,以後時光的值從1970年1月1日開端以秒盤算。在挪用了_ftime()以後,在構造timeBuf的成員millitm中還存入了在以後那一秒曾經渡過的毫秒數,但在DOS中這個數字現實上是以百分之一秒來盤算的。然後,把毫秒數和秒數相加,再和毫秒數停止一次異或運算。你可以對這兩個構造成員施加更多的邏輯運算,以掌握seedVal的取值規模,並進一步增強它的隨機性,但上例所用的邏輯運算曾經足夠了。

留意,在後面的例子中,rand()的輸入並沒有被限制在一個指定的規模內,假定你想樹立一個彩票選號器,其取值規模是從1到44。你可以簡略地疏忽失落rand()所輸入的在該規模以外的值,但這將消費很多時光去獲得所需的全體(例如6個)彩票號碼。假定你曾經樹立了一個令你滿足的隨機數產生器,它所發生的隨機數據規模是從0到32,767(就象前文中提到過的那樣),而你想把輸入限制在1到44之間,上面的例子就解釋了若何來完成這項任務:

int i ,k ,range ;
int rain, max ;
double j ;
min=1;  /* 1 is the minimum number allowed */
max=44;  /* 44 is the maximum number allowed */
range=max-min;  /* r is the range allowed; 1 to 44 */
i=rand();  /* use the above example in this slot */
/* Normalize the rand() output (scale to 0 to 1) */
/* RAND_MAX is defined in stdlib, h */
j= ((double)i/(double)RAND_MAX) ;
/* Scale the output to 1 to 44 */
i= (int)(j * (double)range) ;
i+ =min;

上例把輸入的隨機數限制在1到44之間,其任務道理以下:
獲得一個在O到RAND_MAX(32,767)之間的隨機數,把它除以RAND_MAX,從而發生一個在0到1之間的校訂值;
把校訂值乘以所須要的規模值(在本例中為43,即44減去1),從而發生一個在O到43之間的值;
把該值和所請求的最小值相加,從而使該值終究落在准確的取值規模——1到44以內。

你可以用分歧的min和max值來驗證這個例子,你會發明它老是會准確地發生在新的rain和max值之間的隨機數。

上面來看一下隨機數的相干演習標題

標題
給定了rand7,若何生成rand3?

思緒
一個異常直不雅的思緒,就是赓續的挪用rand7,直到它發生1-3之間的數,然後前往。代碼以下:(假如有同窗說這裡沒有3,然則不代表我不克不及斷定和3的年夜小比擬吧)

 

  #include <stdio.h> 
   
  int rand_3() 
  { 
    int x; 
   
    while (x = rand_7()) { 
      if (x <= 3) { 
        return x; 
      } 
    } 
  } 


接上去,就是斷定rand_3能否能等幾率的發生1,2,3.也就是我們須要盤算發生1,2,3的幾率能否都是1/3.

起首,rand_7可以等幾率的發生1-7,我們以rand_3生成1為例,假定:

  •     第一次生成1的幾率是1/7
  •     第二次生計1的幾率是4/7 * 1/7,是以第一次確定是生成了年夜於3的數例如4,5,6,7,幾率是4/7
  •     同理,第三次生成1的幾率是(4/7)^2 * 1/7

是以,rand_3生成1的幾率是P(x=1)= 1/7 +  (4/7) * 1/7 + (4/7)^2 * 1/7 + ... + (4/7)^n-1 * 1/7 //等比數列
                                                  =  1/7 * ((1 - (4/7)^n) / 1 - 4/7) = 1/7 * 7/3 = 1/3

同理,可驗證生成2,3的幾率均為1/3

結論
上述證實解釋rand3可以等幾率的發生1,2,3.從下面的剖析,我們可以得出一個更普通的結論:

假如a>b,我們必定可以用rand_a去完成rand_b.個中,rand_a是等能夠的生成1-a,rand_b是等能夠的生成1-b

擴大

如今給定兩個生成隨機數的函數rand_a和rand_b,rand_a和rand_b分離發生1-a和1-b的隨機數,a和b不相等,如今讓你用rand_a完成rand_b,辦法以下:

  •     假如a>b,則可以直接采取上述辦法
  •     假如a<b, 則結構rand_a^2=a * (rand_a - 1) + rand_a,表現生成1-a^2的隨機數,假如a^2還小於b,那末持續結構rand_a^3=a * (rand_a^2 - 1) + rand_a


舉例解釋
阿裡2014年口試標題,是給定生成1-7的隨即函數rand_7,看能否能生成其它隨機數?

我們先看一下能否能等幾率生成1-49,結構rand_49 = 7 * (rand_7 - 1) + rand_7 (ps:別問我7從哪裡來的,rand_7既然能隨即生成1-7,我固然可以取得到7了)

rand_7 - 1能等幾率的生成0, 1, 2, 3, 4, 5, 6,每一個數的生成幾率都是1/7,所以*7以後,可以等幾率的生成0,7,14,21,28,35,42,每一個數的幾率都是1/7

既然0,7,14,21,28,35,42每一個數的幾率都是1/7,當每一個數都加上+rand_7以後,則1-49是等幾率發生的,1/7 × 1/7 = 1/49,中央不會湧現反復數據

所以,我們用rand_7發生了rand_49,有了rand_49,依照最後下面過濾的辦法,我們固然可以取得任何小於49的隨機函數


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