C/C++ 使用rand 函數產生隨機亂數教學與範例程式碼 - GT Wang

文章推薦指數: 80 %
投票人數:10人

在撰寫C/C++ 程式時,如果需要產生一些簡單的亂數,最方便的作法就是使用 rand 這個亂數產生函數,以下介紹這個函數的相關用法與範例。

rand 只能提供基本 ... Blogger舊站 關於 Facebook Flickr 物聯網 網站架設 程式設計 統計 素食 特價優惠 宗教 物聯網 網站架設 程式設計 統計 素食 特價優惠 宗教 C/C++使用rand函數產生隨機亂數教學與範例程式碼 2017/04/06 0則留言 本篇介紹C/C++中使用rand函數產生亂數的方法,並且提供各種常用的範例程式碼。

在撰寫C/C++程式時,如果需要產生一些簡單的亂數,最方便的作法就是使用rand這個亂數產生函數,以下介紹這個函數的相關用法與範例。

rand只能提供基本的亂數,如果您需要更進階的功能或是品質比較好的亂數,建議改用C++的函式庫。

基本亂數產生方法 C語言中若要產生亂數,可以使用stdlib.h中的rand函數,而在呼叫rand函數之前,要先使用srand函數設定初始的亂數種子: #include #include/*亂數相關函數*/ #include/*時間相關函數*/ intmain(){ /*設定亂數種子*/ srand(time(NULL)); /*產生亂數*/ intx=rand(); printf("x=%d\n",x); return0; } 執行後的輸出為: x=159136674 rand所產生的亂數是一個整數,其值介於0到RAND_MAX之間(最小是0,最大則為RAND_MAX),若想要看RAND_MAX的實際數值,可以用printf將其輸出後查看。

printf("RAND_MAX=%d\n",RAND_MAX); 在C++中的亂數產生方式也跟C幾乎相同,只是標頭檔換一下而已: #include #include/*亂數相關函數*/ #include/*時間相關函數*/ intmain(){ /*固定亂數種子*/ srand(time(NULL)); /*產生亂數*/ intx=rand(); std::cout< #include #include intmain(){ /*固定亂數種子*/ srand(5); intx=rand(); printf("x=%d\n",x); return0; } x=84035 亂數種子是使用一個整數來做設定的,若要固定亂數種子的話,其數值要設定為多少其實不重要,只要每次執行程式時都使用相同的亂數種子即可。

最常用到固定亂數種子的時機可能就是除錯或是驗證演算法是否有錯誤的時候,如果沒有固定亂數種子的話,每次跑出來的結果都不同,會讓除錯的難度提高。

[0,1)浮點數亂數 若要產生0到1之間的浮點數亂數,可以這樣寫: #include #include #include intmain(){ srand(time(NULL)); /*產生[0,1)的浮點數亂數*/ doublex=(double)rand()/(RAND_MAX+1.0); printf("x=%f\n",x); return0; } 上面的程式中我們將rand函數所產生整數除以RAND_MAX+1.0,就可以得到[0,1)這個範圍的浮點數亂數(也就是0<=x<1)。

特定範圍浮點數亂數 若要產生特定範圍的浮點數亂數,可以這樣寫: #include #include #include intmain(){ srand(time(NULL)); /*指定亂數範圍*/ doublemin=3.6; doublemax=7.8; /*產生[min,max)的浮點數亂數*/ doublex=(max-min)*rand()/(RAND_MAX+1.0)+min; printf("x=%f\n",x); return0; } 這樣即可產生[min,max)之間的浮點數亂數。

特定範圍整數亂數 若想要產生特定範圍的整數亂數,可以這樣寫: #include #include #include intmain(){ srand(time(NULL)); /*指定亂數範圍*/ intmin=4; intmax=10; /*產生[min,max]的整數亂數*/ intx=rand()%(max-min+1)+min; printf("x=%d\n",x); return0; } 這樣會將rand產生出來的整數轉換為[min,max]的整數亂數(也就是min<=x<=max)。

上面這種使用餘數運算(%)的方式只是比較方便的寫法,事實上使用餘數運算所產生的整數亂數在理論上不是標準的均勻分布,我們以一個簡單的例子來解釋,假設RAND_MAX的值為10,而我們要產生介於3到5之間的整數亂數(亦即min=3、max=5),以下是所有的可能性對照表: 轉換後的整數亂數 rand函數產生的亂數 出現機率 3 0、3、6、9 4/11 4 1、4、7、10 4/11 5 2、5、8 3/11 rand函數所產生的每一個整數其出現的機率是均等的,但是經過於數運算的轉換之後,因為RAND_MAX通常不會被整除,所以轉換之後的整數亂數出現機率就存在有細微的偏差,以這個例子來說,3、4、5三個數字出現的機率比是4:4:3。

另外有些人會先產生固定範圍的浮點數亂數,再將浮點數轉型為整數,例如產生[3,6)的浮點數亂數,然後轉型為[3,5]的整數亂數,其實這種方式跟餘數運算一樣會有每個整數出現機率不均等的問題,簡單來說就是現在有11個球要放進3個籃子裡,不管怎麼放,每個籃子的球都不可能一樣多。

如果您需要非常標準的均勻分布(uniformdistribution),可以使用這個版本: /*產生[0,n)均勻分布的整數亂數*/ intrandint(intn){ if((n-1)==RAND_MAX){ returnrand(); }else{ /*計算可以被整除的長度*/ longend=RAND_MAX/n; assert(end>0L); end*=n; /*將尾端會造成偏差的幾個亂數去除, 若產生的亂數超過limit,則將其捨去*/ intr; while((r=rand())>=end); returnr%n; } } 使用這個randint函數產生特定範圍整數亂數: /*指定亂數範圍*/ intmin=4; intmax=10; /*產生[min,max]的整數亂數*/ intx=randint(max-min+1)+min; 這種作法就好像要把11個球要放進3個籃子裡,而最後多出來的2顆球就直接丟掉,確保每個籃子都一樣只有3顆,這樣大家的機率就可以相等了。

這種使用截斷分布(truncateddistribution)來校正機率的方式雖然在理論上是正確的,但是rand函數是使用LCG(LinearCongruentialGenerator)來產生亂數的,他的優點只是快速、方便而已,但它本身所產生的亂數品質沒有非常好,再怎麼校正效果都有限,若需要高品質的亂數,請改用C++11標準的函式庫。

參考資料:Edison.X.Blog、tutorialspoint、StackOverflow、StackOverflow 程式設計 C/C++ G.T.Wang 個人使用Linux經驗長達十餘年,樂於分享各種自由軟體技術與實作文章。

LeaveaReply取消回覆 留言* Name* Email* Website 搜尋 分類Arduino(5) BeagleBoneBlack(1) DIY(54) Linux(316) MacOSX(32) Octave(15) Perl(12) R(47) Windows(97) WordPress(16) 個人(15) 免費(35) 兒童(30) 實用工具(85) 手機(13) 技巧(45) 有趣(99) 樹莓派(57) 物聯網(55) 玄學(11) 生活(209) 程式設計(137) 統計學(8) 網頁空間(36) 網頁開發(128) 虛擬化(7) 農業(42) 遊戲(9) 開箱(131) 雲端(4) 宗教 如何戒邪淫、遠離婚外情 戒淫寶典:《壽康寶鑑》白話有聲書 公益 智邦公益網 igiving公益網 Yahoo奇摩公益 社團法人新竹縣愛心物資集發協會 家扶基金會 ©2022G.T.Wang



請為這篇文章評分?