關於隨機數生成

2021-07-24 17:44:15 字數 3688 閱讀 9698

c++隨機數生成函式rand(),實質生成偽隨機數列。

為生成更加隨機的數列,需要srand(unsigned num)來播種。

常用方式srand((unsigned)time(null));//增加標頭檔案

生成[a,b]之間的隨機整數的方法:

1、rand()%(b-a+1)+a;

2、a+b*rand()/rand_max;

兩篇引用博文:第一篇講了基本的方法,第二篇講了一些限制條件。其實對於第二篇的情況,在隨機數的範圍有限的情況下,不等概率的影響是可以忽略不計的,但是當隨機數區間長度很大時候,上述問題就變得比較有意義了。特別是當區間長度大於rand_max的一半以上時,這種情況就需要認真處理了。

daisy's blog

**:計算機的隨機數都是由偽隨機數,即是由小m多項式序列生成的,其中產生每個小序列都有乙個初始值,即隨機種子。(注意: 小m多項式序列的週期是65535,即每次利用乙個隨機種子生成的隨機數的週期是65535,當你取得65535個隨機數後它們又重複出現了。) 

我們知道rand()函式可以用來產生隨機數,但是這不是真正意義上的隨機數,是乙個偽隨機數,是根據乙個數(我們可以稱它為種子)為基準以某個遞推公式推算出來的一系列數,當這系列數很大的時候,就符合正態公布,從而相當於產生了隨機數,但這不是真正的隨機數,當計算機正常開機後,這個種子的值是定了的,除非你破壞了系統。

1.rand()

功能:隨機數發生器

用法:int rand(void)

所在標頭檔案: stdlib.h

rand()的內部實現是用線性同餘法做的,它不是真的隨機數,因其週期特別長,故在一定的範圍裡可看成是隨機的。

rand()返回一隨機數值的範圍在0至rand_max 間。rand_max的範圍最少是在32767之間(int)。用unsigned int 雙位元組是65535,四位元組是4294967295的整數範圍。0~rand_max每個數字被選中的機率是相同的。

使用者未設定隨機數種子時,系統預設的隨機數種子為1。

rand()產生的是偽隨機數字,每次執行時是相同的;若要不同,用函式srand()初始化它。

2.srand()

功能:初始化隨機數發生器

用法: void srand(unsigned int seed)

所在標頭檔案: stdlib.h

srand()用來設定rand()產生隨機數時的隨機數種子。引數seed必須是個整數,如果每次seed都設相同值,rand()所產生的隨機數值每次就會一樣。

3.使用當前時鐘作為隨機數種子

rand()產生的隨機數在每次執行的時候都是與上一次相同的。若要不同,用函式srand()初始化它。可以利用srand((unsigned int)(time(null))的方法,產生不同的隨機數種子,因為每一次執行程式的時間是不同的。

4.產生隨機數的用法

1) 給srand()提供乙個種子,它是乙個unsigned int型別;

2) 呼叫rand(),它會根據提供給srand()的種子值返回乙個隨機數(在0到rand_max之間);

3) 根據需要多次呼叫rand(),從而不間斷地得到新的隨機數;

4) 無論什麼時候,都可以給srand()提供乙個新的種子,從而進一步「隨機化」rand()的輸出結果。

0~rand_max之間的隨機數程式

#include

#include

#include

using

namespace

std; 

intmain()

5.產生一定範圍隨機數的通用表示公式

要取得[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)。

如果讓你用c++來生成0——n-1之間的隨機數,你會怎麼做?你可能會說,很簡單,看:

srand( (unsigned)time( null ) );

rand() % n;

仔細想一下,這個結果是隨機的嗎(當然,我們不考慮rand()函式的偽隨機性)?

不是的,因為rand()的上限是rand_max,而一般情況下,rand_max並不是n的整數倍,那麼如果rand_max % = r,則0——r之間的數值的概率就要大一些,而r+1——n-1之間的數值的概率就要小一些。還有,如果n > rand_max,那該怎麼辦?

下面給出一種比較合適的方案,可以生成任意範圍內的等概率隨機數 result。最後還有乙個更簡單的方法。

1、如果n

r = rand_max-(rand_max+1)%n; //去除尾數

t = rand();

while( t > r ) t = rand();

result = t % n; // 符合要求的隨機數

2、如果 n>rand_max,可以考慮分段抽樣,分成[n/(rnad_max+1)]段,先等概率得到段再得到每段內的某個元素,這樣分段也類似地有乙個尾數問題,不是每次都剛好分到整數段,一定或多或少有乙個餘數段,這部分的值如何選取?

選到餘數段的資料拿出來選取,先進行一次選到餘數段概率的事件發生,然後進行單獨選取:

r = n % (rand_max+1); //餘數

result = n-r+myrandom(r); // myrandom可以用情況1中的**實現

else

result = rand()+myrandom(n/(rand_max+1))*(rand_max+1); // 如果選不到餘數段再進行分段選取

if(probability<=0)

if(probability

if(rand()<=probability*(rand_max+1))

return false;

}long myrandom(long n)//產生0~n-1之間的等概率隨機數

return t % n;

} else

else  }

} 還有另外一種非常簡單的方式,那就是使用

random_shuffle( randomaccessiterator _first, randomaccessiterator _last ).

例如,生成0——n-1之間的隨機數,可以這麼寫

#include

#include

long myrandom( long n )

std::random_shuffle( vl.begin(), vl.end() );

return (*vl.begin());

}random_shuffle 還有乙個三引數的過載版本

random_shuffle( randomaccessiterator _first, randomaccessiterator _last, randomnumbergenerator& _rand )

第三個引數可以接受乙個自定義的隨機數生成器來把前兩個引數之間的元素隨機化。

這個方法的缺陷就是,如果只是需要乙個隨機數的話,當n很大時,空間消耗很大!

**----- 

關於隨機數生成

很多學計算機的學生大學四年學下來連隨機數是怎麼產生的都弄不明白,更有甚者連隨機函式怎麼呼叫都搞不清楚,這不能不說是一種悲哀。嗯,現在讓我們一起使這種悲哀成為歷史吧 首先我們要搞清楚乙個概念,生成單個的隨機數是沒有意義的,我們所說的隨機數生成,其實都是生成乙個隨機序列。鑑於人們通常對具體的做法比對分析...

關於隨機數生成

涉及到skip lists的時候,基本上概率會選擇1 2,那麼需要多次生成0 1的隨機數。由於要多次生成隨機數,而隨機數的生成會極大的影響程式的執行效率。所以想到可不可以通過生成更大的隨機數來降低效率。比如兩次需要0 1的隨機數,可以通過一次0 3的隨機數m來代替。m 1和m 1 1 分別表示兩個隨...

隨機生成隨機數

現畫乙個command命令按鈕,進行貼上。private sub command1 click show me scale 0,0 18,8 me.auto redraw true me.draw mode 2 circle 3,4 3,vb red me.auto redraw false lin...