乱数及び確率による乱数の生成


インスタンス1は、単純に乱数を生成します.
#include 
#include 
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);
}


この種は翌日に大量の重複データが発生すると,連続的な長時間の応用に合わない.
例2、主に種子の発生を改善する
#include 
#include 
#include 
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);
}



例3、重複データを生成しないランダムな方法
#include 
#include 
#include 
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

例4、一定の確率で乱数(確率100%)を生成する
方法例:1 20%2 30%3 50%
20個の1、30個の2、50個の3をランダムに配列に入れ、ランダムに1-100を出して、対応する数字の下に表示された数字を出すことができます.
方法2:
かくりつで区切る
10個の数字1 2は1を表し、3 4 5は3を表し、6 7 8 9 10は数字5を表し、一定の確率のランダムな数字を生成する.
例:
#include 
#include 
#include 
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) << "% "<

例5は、一定の確率で乱数(非100%)を生成する
コードの例:
int a=20,b=7,c=13,d=9,e=15; a   20/64=0.3125 b 7/64=0.1093........
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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

乱数が発生しても精巧ではないかもしれませんが
解析結果:
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 
#include 
#include 
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)を使用します.