C語言中可以使用rand()函數來生成一個從0到RAND_MAX的uniform分布。基於這個函數,我們可以構造出一些特定的隨機數生成器來滿足我們的需求。
(一)0到1的uniform分布:
//generate a random number in the range of [0,1] double uniform_zero_to_one(){ return (double)rand()/RAND_MAX; }
(二)任意實數區間的uniform分布:
//generate a random real number in [start,end] double uniform_real(double start,double end){ double rate=(double)rand()/RAND_MAX; return start+(end-start)*rate; }
(三)任意整數區間的uniform分布:
//generate a random integer number in [start,end) int uniform_integer(int start,int end){ int base=rand(); if(base==RAND_MAX) return uniform_integer(start,end); int range=end-start; int remainder=RAND_MAX%range; int bucket=RAND_MAX/range; if(base<RAND_MAX-remainder) return start+base/bucket; else return uniform_integer(start,end); }
這個函數要特別說明一下,平常時候我們都是用rand()%n來生成0到n-1的隨機數,但是按這種方法生成的分布並不是uniform的,更詳細的討論可以參見stackoverflow http://stackoverflow.com/questions/2509679/how-to-generate-a-random-number-from-within-a-range-c。另外,我這個函數也是從stackoverflow上獲得,不敢據為己有,此處只為和大家分享。
另外由於RAND_MAX只有32767,因此要生成比這個數更大的隨機數需要另外想辦法,理論上可以直接用0到1的uniform分布直接放縮,但實際效果不好。這里給出一種移位方式的實現。
(四)32bits的隨機數
//generate a random 32 bits integer number int rand32(){ return ((rand()<<16)+(rand()<<1)+rand()%2); }
有了32bits的隨機數生成方法,就可以構造32bits范圍內的隨機整數區間了,方法和之前16bits的情況一樣。
(五)32bits范圍內的隨機整數區間
//generate a random 32bits integer number in [start,end) int uniform_integer_32(int start,int end){ int base=rand32(); if(base==RAND32_MAX) return uniform_integer_32(start,end); int range=end-start; int remainder=RAND32_MAX%range; int bucket=RAND32_MAX/range; if(base<RAND32_MAX-remainder) return start+base/bucket; else return uniform_integer_32(start,end); }
這里RAND32_MAX定義為0x7fffffff。
除此之外,利用rand()函數構造任意分布的隨機數也是個值得探討的問題。
理論上可以通過(0,1)的uniform分布,加上標准采樣方法(sampling)獲得。但是實現還是不那么容易的。之前在CSDN上看到有人推薦Intel MKL庫(Intel MKL Vector Statistical Library (VSL) is a collection of 9 random number generators and 22 probability distributions that deliver significant performance improvements in physics, chemistry, and financial analysis.)這個庫包括了常見的隨機數生成器,以及可以生成常見的隨機數分布。
偽隨機數其實是一個很值得研究的課題,這里只是拋磚引玉,歡迎討論,歡迎提出更好的方法。
續一:在本文發布后,有人提出來boost庫有關於隨機數的東西,我查了一下,確實如此。這里給出boost庫隨機數文檔的鏈接:http://www.boost.org/doc/libs/1_35_0/libs/random/index.html
續二:C++ 11開始標准庫也自帶了隨機數的函數,詳細請參見相關文檔:http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution