隨機數及按照概率生成隨機數
阿新 • • 發佈:2019-02-18
例項一簡單生成隨機數:
#include <iostream> #include <cstdlib> using namespace std; int Random(double min, double max); int main(int argc, char *argv[]) { srand((int)time(NULL)); int t=0; for(int i=0;i<10;++i) { t = Random(1, 11); cout << t << " "; } cout << endl; return 0; } int Random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); }
這種種子如果在第二天會出現大量重複資料,不符合連續長時間的應用
例項二,主要改進種子的產生
#include <iostream> #include <cstdlib> #include <sys/timeb.h> using namespace std; int Random(double min, double max); int main(int argc, char *argv[]) { unsigned int seedVal; struct timeb timeBuf; ftime(&timeBuf); seedVal=((((unsigned int)timeBuf.time & 0xFFFF)+ (unsigned int)timeBuf.millitm)^ (unsigned int)timeBuf.millitm); srand((unsigned int)seedVal); int t=0; for(int i=0;i<10;++i) { t = Random(1, 11); cout << t << " "; } cout << endl; cout << timeBuf.millitm << " " << ( timeBuf.millitm^timeBuf.millitm) << endl; return 0; } int Random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); }
例項三,不產生重複資料的隨機方法
#include <iostream> #include <cstdlib> #include <sys/timeb.h> using namespace std; int N=100,M=10; int a[100],b[100]; int Random(double min, double max); int NorepeatRandom(double start, double end); int NorepeatRandom2(double start, double end); int main(int argc, char *argv[]) { unsigned int seedVal; struct timeb timeBuf; ftime(&timeBuf); seedVal=((((unsigned int)timeBuf.time & 0xFFFF)+ (unsigned int)timeBuf.millitm)^ (unsigned int)timeBuf.millitm); srand((unsigned int)seedVal); // NorepeatRandom(0,0); NorepeatRandom2(0,0); for(int i=0; i< M;++i) { cout << b[i] << " "; } cout << endl; return 0; } //repeat random int Random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } //not repeate random int NorepeatRandom(double start, double end) { int i,j,k; for (i=0;i<N;i++) a[i]=i+1; for(i=0;i<M;i++) { j=rand()%(N-i); b[i]=a[j]; for(k=j;k<N-i-2;k++) a[k]=a[k+1]; } } int NorepeatRandom2(double start, double end) { int i=0; for(i=0;i<N;i++) { a[i]=i+1; } i = rand()%(N-1); a[i] = 1; b[0] = i; for(int j=1;j< M;) { while((i=rand()%N) && (a[i]!= 1)) { b[j++] = i; a[i] = 1; break; } } }
例項四,按照一定概率產生隨機數(概率為100%)
方法舉例:1 20% 2 30% 3 50%
可以將20個1,30個2 , 50 個3 隨機放入陣列中,然後隨機1-100,拿出對應數字下標下的數字。
方法二:
按照概率進行區間劃分
10個數字1 2 代表1,3 4 5代表3, 6 7 8 9 10代表數字5,從而產生一定概率的隨機數字
例項:
#include <iostream>
#include <cstdlib>
#include <sys/timeb.h>
using namespace std;
int Random(double min, double max);
int main(int argc, char *argv[])
{
unsigned int seedVal;
struct timeb timeBuf;
ftime(&timeBuf);
seedVal=((((unsigned int)timeBuf.time & 0xFFFF)+
(unsigned int)timeBuf.millitm)^
(unsigned int)timeBuf.millitm);
srand((unsigned int)seedVal);
//1 20% 2 30% 3 50%
int i = 0, t;
int n1=0,n2=0,n3=0;
while(++i<100000)
{
t = Random(1, 11);
if(t<=0 || t>10)
break;
switch(t)
{
case 1:
case 2:
++n1;
break;
case 3:
case 4:
case 5:
++n2;
break;
case 6:
case 7:
case 8:
case 9:
case 10:
++n3;
break;
defalt:
break;
}
}
cout << ((double)n1/100000*100) << "% " << ((double)n2/100000*100) << "% "<<((double)n3/100000*100) <<"% "<< endl;
return 0;
}
int Random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
例項5,按照一定概率產生隨機數(非100%)
程式碼示例:
int a=20,b=7,c=13,d=9,e=15; a概率為20/64=0.3125 b 7/64=0.1093........
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <map>
#include <sys/timeb.h>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int Random(double min, double max);
int Random2(int low, int high);
void shuffle2(int* cards, int n);
string num2str(int num)
{
stringstream ss;
ss << num;
return ss.str();
}
int main(int argc, char *argv[])
{
unsigned int seedVal;
struct timeb timeBuf;
ftime(&timeBuf);
seedVal=((((unsigned int)timeBuf.time & 0xFFFF)+
(unsigned int)timeBuf.millitm)^
(unsigned int)timeBuf.millitm);
srand((unsigned int)seedVal);
int a=20,b=7,c=13,d=9,e=15;
int tol = a+b+c+d+e;
int *arr = new int[tol];
for(int i=0;i<a;++i)
arr[i]=1;
for(int i=a;i<a+b;++i)
{
arr[i]=2;
}
for(int i=a+b;i<a+b+c;++i)
arr[i]=3;
for(int i=a+b+c;i<a+b+c+d;++i)
arr[i]=4;
for(int i=a+b+c+d;i<tol;++i)
arr[i] = 5;
shuffle2(arr, tol);
for(int i=0;i<tol;++i)
{
cout << arr[i]<<" ";
}
cout << endl;
int tmparr[tol];
memcpy(&tmparr[0], &arr[0], sizeof(tmparr));
for(int i=0;i<tol;++i)
{
cout << tmparr[i]<<" ";
}
cout << endl;
int j=0,pos;
int tmp[4];
int i=0;
string s,s1,s2,s3,s4;
ofstream outfile("./record", ofstream::out|ofstream::app);
while(++i<1000000)
{
while(1)
{
pos = Random2(1,55);
if(tmparr[pos]<0)
continue;
if(j==4)
break;
tmp[j] = tmparr[pos];
for(int i=0;i<tol;++i)
{
if(tmparr[i] == tmp[j])
tmparr[i] = -1;
}
j++;
}
s1 = num2str(tmp[0]);
s2 = num2str(tmp[1]);
s3 = num2str(tmp[2]);
s4 = num2str(tmp[3]);
s = s1+"|"+s2+"|"+s3 + "|"+s4;
cout << s <<endl;
if(!outfile)
cout << "open record file error\n";
outfile<< s <<endl;
outfile<<endl;
cout << endl;
memset(tmp,0, sizeof(int));
memcpy(&tmparr[0], &arr[0], sizeof(tmparr));
j=0;
}
outfile.clear();
outfile.close();
return 0;
}
int Random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
int Random2(int low, int high)
{
return low + rand() % (high - low + 1);
}
void shuffle2(int* cards, int n)
{
for (int i = 0; i < n; i++)
{
int rand = Random2(0, i);
int temp = cards[rand];
cards[rand] = cards[i];
cards[i] = temp;
}
}
可能隨機數產生還是不夠精卻
分析結果:
total=999999
1=0.328019%
2=0.127217%
3=0.181625%
4=0.126948%
5=0.23619%
還有一種思路:
int a=20,b=7,c=13,d=9,e=15
總和為:64,隨機1-64的數,假如為34, a+b+c >34,則隨機數為13,然後將c置為0,在求和,再次隨機,依次下去...假設隨機3個數字終止。
例項:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
static int k[6][2];
int a[] = {12, 34, 21, 32, 9, 16}; //設定概率
void initdata()
{
srand(time(NULL));
for(int i=0;i<6;++i)
{
k[i][0] += a[i];
}
for(int i=0;i<6;++i)
{
k[i][1] = 0;
}
}
void setarray()
{
for(int i=0;i<6;i++)
{
k[i][1] = 0;
}
}
int getonerand()
{
int tol = 0;
for (int i=0; i<6; i++)
{
if (k[i][1] == 0)
tol = tol + k[i][0];
}
int d = 1+(int)(1.0*tol*rand()/(RAND_MAX+1.0));
int tmpsum = 0;
for(int i=0; i<6; i++)
{
if (k[i][1] == 0)
{
tmpsum = tmpsum + k[i][0];
if (tmpsum >= d)
{
k[i][1] = 1;
return (i);
}
}
}
}
int main(int argc, char *argv[])
{
initdata();
int j=0;
while(j++ < 30)
{
for(int i=0;i<4;++i)
{
int t = getonerand();
cout << a[t] << " ";
}
cout << endl;
setarray();
}
return 0;
}
利用簡單洗牌演算法生成不重複的隨機數:
void shuffle2(int* cards, int n)
{
// 隨機i-1中的任意一個數與i交換
for (int i = 0; i < n; i++)
{
int rand = Random2(0, i);
int temp = cards[rand];
cards[rand] = cards[i];
cards[i] = temp;
}
}
int* shuffle(int* cards, int n)
{
if (n <= 0)
return cards;
shuffle(cards, n - 1);
int rand = Random2(0, n);
int temp = cards[rand];
cards[rand] = cards[n];
cards[n] = temp;
return cards;
}
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)。