[C&++] 亂數基本使用@ Edison.X. Blog

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

[亂數] C/C++ 亂數基本使用與常見問題 ... 接著呼叫rand() 便可產生隨機亂數,隨機亂數的範圍為0 ~RAND_MAX,RAND_MAX 為一macro,在我的電腦 ... Edison.X.Blog 跳到主文 YouLoveMe()?LetItBe():LetMeFree(); 部落格全站分類:數位生活 相簿 部落格 留言 名片 Nov24Wed201004:32 [C&++]亂數基本使用 這篇筆者認為寫得沒系統,對初學者而言不夠清楚,有些地方也寫錯,有興趣可參考另一篇  [亂數]C/C++亂數基本使用與常見問題  ,本文予以關閉。

 前言: 1.亂數部份吾人有所「輕微長進」,有空時將再為此文進行修改,以期本文更加完整。

錯誤部份、不佳部份並不予以刪除,因這些極有可能為他人會犯之點。

吾人亂數部份受JacobLee指導甚多,在此特別感謝! 2.亂數的分佈情形不只一種,這裡探討的是「均勻分佈」(其它分佈有機會再補上)。

3.待補上Knuth-shfftle -----------------分隔線-----------------分隔線-----------------分隔線-----------------  1.初始化 C/C++底上,若要產生一亂數會用到的表頭檔如下: #include//srand 與rand,C++為cstdlib#include //time(),C++為ctime 在初始化時,必須先設定亂數種子,否則每次跑出來的亂數都一樣,且需注意件事,以time為亂數種子時,仍每秒更新一次,故srand事實上沒必要(也不能)放在loop 裡面一直執行。

設定亂數種子方法如下所示: srand(time(NULL)); 另外,整個程式中,亂數種子只需設一次便可,所以srand沒必要放在回圈裡面,那只會使執行速度變慢。

C裡之rand()使用的是uniformdistribution。

其餘的bernoulli、binomial、...etc,去MSDN下載VisualC++2008FeaturePackRelease,裡面有進行支援。

2.取得亂數 接著呼叫rand()便可產生隨機亂數,隨機亂數的範圍為0~RAND_MAX,RAND_MAX為一macro,在我的電腦與Complier底下是被定義為32767。

以下例子便示範跑100遍亂數。

for(inti=0;i<100;i++)rand(); 3.設亂數範圍(1~6之整數) 像是擲骯子,它的點數就只有1~6點,我們可以這麼做 rand()%6+1;//worst rand()%6的結果一定是落於0~5間之整數,把這結果加1後,便成為1~6之間的整數。

[Lemma] 這種方式重覆機率很高,對於「均勻」條件差了點,使用下面方式較為佳: (int)( (6-1)*(double)rand()/RAND_MAX)+1; 4.設亂數範圍([-2,2]之整數) 這裡和上面差不多,以整數來看,-2~+2中間有5個整數(-2,-1,0,1,2),於是我們可以這麼做 rand()%5-2; rand()%5之結果必落於0~4之間,把這結果減2後,便成為-2~+2之整數。

於是我們可得到一歸納,要取得low與up之間之整數亂數為 rand()%(up-low+1)+low [Lemma] 為符合均勻性,較常使用這種方式做: (up-low)*(double)rand()/RAND_MAX+low; 此法不論是整數或浮點數均適用!若浮點數要考慮是小數後幾位,可再用此法進行四捨五入等方式做調整。

5.設亂數範圍([-1,1]之浮點數) (5.1)設[0,1]之浮點數亂數 剛有介紹過,使用rand時,其最大值為RAND_MAX,於是若要設0~1亂數便這麼做 (double)rand()/RAND_MAX; 加上double是為了強制轉成浮點數,避免產生相除等於零之情形。

[Lemma] 加註區間性問題(感謝Jacob Lee提醒) 產生[0,1)之浮點數:(double)rand()/(RAND_MAX+1);產生[0,1]之浮點數:(double)rand()/RAND_MAX;產生(0,1)之浮點數:(double)(rand()+1)/(RAND_MAX+2);//思考是否有其他問題存在中產生(0,1]之浮點數:(double)(rand()+1)/(RAND_MAX+1);//思考是否有其他問題存在中 (5.2)產生[-1,+1]之浮點亂數 這種做法起碼三種,我只說較簡單的方法。

雖產生[0,1],但實際上要產生的是[-1,1],由於間隔為2,所以把分子乘以二倍再除上RAND_MAX。

(double)rand()*2/RAND_MAX+(-1); 於是我們產生了一通式:[up,down]--->(double)rand()*(up-down)/RAND_MAX+down; 6.取得N個1~X不重覆亂數,其中X>N (6.1)撲克洗牌法 建立X張撲克牌,點數為1~X,隨機抽二張牌交法(抽的次數有人說X/2次,也有人說抽X次),最後再從牌堆裡面拿出N張出來。

inti,t1,t2,Array[X],tmp;//x張pokerfor(i=0;i10000 於是我將所產生出之亂數乘上4倍再mod10000。

rand()*4%10000; 有時這樣便可滿足需求,有時則否。

不能滿足的原因大多如下 rand()=1-> 1*4%100000=4rand()=2-> 2*4%100000=4 沒錯,這樣下去產生的亂數永遠都是4的倍數, 可參考以下之解法 (rand()*4%100000+rand()%4)%100000; 我以前是這麼做,但說真的連我自己都覺得麻煩、很糟。

----------分隔線 ----------分隔線----------分隔線----------分隔線------- 另可考慮第二種做法: rand()範圍為0~RAND_MAX=0~32767,使用了15bits;於是可考慮: intrnd=rand()|(rand()<<15); 這樣便生成了30bits之亂數,範圍便展開成了0~2^30-1=1,073,741,824(約10億,10^9),到時再進行mod運算,但這種方式絕不可能會使得rnd=0 (連續取二個rand()若數值相同,那這個產生器是失敗的!) 類似要擴展的方式也類似,但聲明,這些方式都有著「不均勻」問題,同時有些數字可能都不會出現的問題 intrand31(){   //RAND31_MAX= 2147483647   return((rand()<<16) |(rand()<<1) |(rand()&1));} unsignedintrand32(){   //RAND32_MAX=4294967295   return((rand()<<17) |(rand()<<2) |(rand()&3));} 要徹底解決這個問題,我想除了找lib,換complier,再來就是自己寫亂數產生器了。

8.其他函式庫 (8.1)c++STL-random_shuffle 使用random_shuffle去洗 constintN=8;intA[]={1,2,3,4,5,6,7,8};random_shuffle(A,A+N); (8.2)網路提供之函式庫與說明 MersenneTwister :Wiki C/C++download MonteCarlomethodsinWiki VisualC++2008FeaturePackRelease:這個強烈建議一定要去載來安裝!裡面加強了許多功能,其中亂數也加強了很多(待吾人研究後慢慢發心得)   ----------分隔線 ----------分隔線----------分隔線----------分隔線------- [亂數可研究議題、文獻甚多,若有興趣可再深入研究。

]   全站熱搜 創作者介紹 edisonx Edison.X.Blog edisonx發表在痞客邦留言(0)人氣() E-mail轉寄 全站分類:數位生活個人分類:亂數此分類下一篇:[C&++]測試亂數週期 上一篇:vector心得整理 下一篇:[C]printf引數說明 歷史上的今天 2011:[C&++]遞回函式究竟該用怎樣的引數? 2010:[C]printf引數說明 ▲top 留言列表 禁止留言 站方公告 [公告]2022年度農曆春節期間服務公告[公告]MIB廣告分潤計劃、PIXwallet錢包帳戶條款異動通知[公告]2021年度農曆春節期間服務公告 活動快報 潮Way台南大富翁 最新潮、最有話題的「潮Way台南」指南,擁有網友推... 看更多活動好康 我的好友 熱門文章 文章分類 開發手札(2) 未實作的想法(4)心得筆記(2) C/C++(8) C/C++Note(52)亂數(10)Debug(9)HiddenFeaturesinC(6)面試題庫(12)OONOTE(0)C/C++FAQ(4)STLNote(3) 應用軟體/工具(1) Office(1) 數值分析(9) 非線性方程式求解(10)矩陣運算(7)深入質數(5)浮點數(9)複數Complex(2)積分法(2)多項式內差法(2)常見關於數(5)math.h/cmathapplication(8) 程式之美(1) 遊戲之樂(3) VB.Net(1) VB.NetNote(1) 英文(1) 專題單字(1) AutoIt!!(2) AutoIt!!Note(13)Auto-Dll(9) VBA(4) VBANote(9)VBAFAQ(5)VBAtec.(1)VBA_Note2(3) MFC(1) MFC雜記(4) Win32(8) Win32-Console(5)Process(10)檔案系統(1)音效(1)隱喻外掛(3)GDI(2)Systemundoc.(0)記憶體管理(1) 環境與Script(5) visualstudio(6)批次檔batch(2)VBS(0)程式環境架構(3)Library(3) 數學整理(2) 有趣數學(2)常用公式(1) 演算法(7) AI(13)Bit-Hacks(1)大數(5)資料結構(0)影像(2)遞迴-recursive(2)回溯.列舉.遞迴(2) 程設亂語(1) 胡言亂語(11) SmallTalk(1) SmallTalk(27) 最新文章 最新留言 動態訂閱 文章精選 文章精選 2017二月(1) 2016十月(1) 2014四月(1) 2014三月(1) 2014二月(2) 2014一月(1) 2013九月(2) 2013五月(1) 2013一月(3) 2012十二月(10) 2012十一月(6) 2012十月(4) 2012八月(1) 2012七月(13) 2012六月(17) 2012五月(2) 2012四月(15) 2012三月(9) 2012一月(4) 2011十二月(7) 2011十一月(33) 2011十月(8) 2011九月(8) 2011八月(11) 2011七月(3) 2011六月(7) 2011五月(12) 2011四月(13) 2011三月(5) 2011二月(1) 2011一月(31) 2010十二月(34) 2010十一月(22) 2008六月(1) 2008五月(1) 2008三月(11) 2007十一月(1) 2005十一月(2) 所有文章列表 文章搜尋 新聞交換(RSS) 誰來我家 參觀人氣 本日人氣: 累積人氣: QRCode POWEREDBY (登入) {{article.user_name}} {{article.timestamp*1000|date:'MMM.dd.y.hh.mm'}} {{article.title}} {{article.content}} 我要留言 回到頁首 回到主文 免費註冊 客服中心 痞客邦首頁 ©2003-2022PIXNET 關閉視窗 PIXNET Facebook Yahoo! Google MSN {{guestName}} (登出) 您尚未登入,將以訪客身份留言。

亦可以上方服務帳號登入留言 請輸入暱稱(最多顯示6個中文字元) 請輸入標題(最多顯示9個中文字元) 請輸入內容(最多140個中文字元) 請輸入左方認證碼: 看不懂,換張圖 請輸入驗證碼 送出留言



請為這篇文章評分?