本文主的主要內容是一些隨機算法,主要有四種,下面來詳細的介紹:
1 生成隨機數
一般c語言中提供了隨機數生成函數,
其一是偽隨機數--rand:用於返回一個0-32767之間的偽隨機數;
其二是隨機種子函數--srand:用來初始化隨機數發生器的隨機種子
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int i,j; srand((int)time(0)); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { printf("%d ",rand()); } printf("\n"); } return 0; }
當然也可以生成一定范圍內的隨機數
比如生成0——100之間的隨機數
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int i,j; srand((int)time(0)); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { printf("%d ",rand()*100/32767); } printf("\n"); } return 0; }
也可以生成100——200之間的隨機數
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int i,j; srand((int)time(0)); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { printf("%d ",rand()/1000+100); } printf("\n"); } return 0; }
2 生成[0,1]之間均勻分布的隨機數算法
在這里采用一種方式生成隨機數
其中i=1,2,3.。。。
而pi就是地推倒的第i個隨機數
根據經驗,一般選取基數base=256.0,一般為2的整數倍;另外的兩個常數選取a=17.0 和b=139.0
需要注意
(1)這里的取模運算是針對浮點型數據的,而c語言中的取模運算不能用於浮點數數據的操作,這樣就需要用戶自己編寫取模的程序;
(2)ri是隨着遞推而每次更新的。因此,如果將這個算法編寫出函數,需要考慮參數是傳值還是傳地址;
遞推更新,所以在這里要傳地址,否則得不到結果!
#include <stdio.h> double rand0_1(double *r) { double base=256.0; double a=17.0; double b=139.0; double temp1=a*(*r)+b; //printf("%lf",temp1); double temp2=(int)(temp1/base); //得到余數 double temp3=temp1-temp2*base; //printf("%lf\n",temp2); //printf("%lf\n",temp3); *r=temp3; double p=*r/base; return p; } int main() { double r=5.0; printf("output 10 number between 0 and 1:\n"); for (int i = 0; i < 10; i++) { printf("%10.5lf\n",rand0_1(&r)); } return 0; }
3 產生任意范圍內的隨機數,比如產生[m,n]之間的隨機數
這個很容易,只要將之前的[0,1]之間的隨機數這樣處理就行了
m+(m-n)*rand0_1(&r)就行了;
#include <stdio.h> double rand0_1(double *r) { double base=256.0; double a=17.0; double b=139.0; double temp1=a*(*r)+b; //printf("%lf",temp1); double temp2=(int)(temp1/base); //得到余數 double temp3=temp1-temp2*base; //printf("%lf\n",temp2); //printf("%lf\n",temp3); *r=temp3; double p=*r/base; return p; } int main() { double m=1.0,n=5.0; double r=5.0; printf("output 10 number between 0 and 1:\n"); for (int i = 0; i < 10; i++) { printf("%10.5lf\n",m+(n-m)*rand0_1(&r)); } return 0; }
4 正態分布的隨機數生成算法
符合正太分布的隨機數在研究中也很重要,下面給出一種生成正態分布數的方法

其中Ri表示[0,1]之間均勻分布的隨機數;
u為均值,
為方差,當n趨向於無窮大的時候,得到隨機的隨機分布為正態分布;
為方差,當n趨向於無窮大的時候,得到隨機的隨機分布為正態分布;
#include <stdio.h> #include <math.h> double rand0_1(double *r) { double base=256.0; double a=17.0; double b=139.0; double temp1=a*(*r)+b; //printf("%lf",temp1); double temp2=(int)(temp1/base); //得到余數 double temp3=temp1-temp2*base; //printf("%lf\n",temp2); //printf("%lf\n",temp3); *r=temp3; double p=*r/base; return p; } double random_normality(double u,double t,double *r ,double n) { double total=0.0; double result; for (int i = 0; i < n; i++) { total+=rand0_1(r); } result=u+t*(total-n/2)/sqrt(n/12); return result; } int main() { double r=5.0; double u=2.0; double t=3.5; double n=12; printf("output 10 number between 0 and 1:\n"); for (int i = 0; i < 10; i++) { printf("%10.5lf\n",random_normality(u,t,&r,n)); } return 0; }
上面設計的代碼都已經運行通過!
補充知識點:leveldb中使用了一個簡單的方式來實現隨機化數;算法的核心是seed_ = (seed_ * A) % M,
下面把源代碼貼出來,不難,可以和上面的參考下
private: uint32_t seed_; public: explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { // Avoid bad seeds. if (seed_ == 0 || seed_ == 2147483647L) { seed_ = 1; } } uint32_t Next() { static const uint32_t M = 2147483647L; // 2^31-1 static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 // We are computing // seed_ = (seed_ * A) % M, where M = 2^31-1 // // seed_ must not be zero or M, or else all subsequent computed values // will be zero or M respectively. For all other values, seed_ will end // up cycling through every number in [1,M-1] uint64_t product = seed_ * A; // Compute (product % M) using the fact that ((x << 31) % M) == x. seed_ = static_cast<uint32_t>((product >> 31) + (product & M)); // The first reduction may overflow by 1 bit, so we may need to // repeat. mod == M is not possible; using > allows the faster // sign-bit-based test. if (seed_ > M) { seed_ -= M; } return seed_; } // Returns a uniformly distributed value in the range [0..n-1] // REQUIRES: n > 0 uint32_t Uniform(int n) { return Next() % n; } // Randomly returns true ~"1/n" of the time, and false otherwise. // REQUIRES: n > 0 bool OneIn(int n) { return (Next() % n) == 0; } // Skewed: pick "base" uniformly from range [0,max_log] and then // return "base" random bits. The effect is to pick a number in the // range [0,2^max_log-1] with exponential bias towards smaller numbers. uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); } };
這里面也直接取模得到一定范圍內的隨機數,簡單明了。
