一定範囲の乱数を生成


</pre><pre name="code" class="cpp">#include <iostream>
using namespace std;
const float MAXWEIGHT = 0.3;
const float SCALEWEIGHT = 32767;
void main()
{
float frand=rand();
float frand1 = rand();
					float a=MAXWEIGHT*(1.0-2*frand/SCALEWEIGHT);
					float b=MAXWEIGHT*(1.0-2*frand1/SCALEWEIGHT);
					cout<<a<<" "<<b<<endl;
					system("pause");
}

計算機の乱数はいずれも擬似乱数,すなわち小M多項式シーケンスによって生成され,生成された各小シーケンスには初期値,すなわちランダムシードがある.(注意:小M多項式シーケンスの周期は65535であり、すなわち、ランダムシードを1つ利用して生成されるランダム数の周期は65535であり、65535個のランダム数を取得すると再び繰り返される.) 
 
rand()関数は乱数を生成するために使用できることを知っていますが、これは本当の意味での乱数ではなく、擬似乱数であり、1つの数(種子と呼ぶことができます)を基準にある繰返し式で推定された一連の数であり、この一連の数が大きい場合、正規公表に合致し、乱数を生成することに相当します.しかし、これは本当の乱数ではありません.コンピュータが正常に起動した後、このシードの値はシステムを破壊しない限り、決まっています.
 
1.rand()
機能:乱数発生器
 
使用法:int rand(void)
 
所在ヘッダファイル:stdlib.h
 
rand()の内部実装は線形同余法で行われ,真の乱数ではなく,その周期が特に長いため,一定の範囲でランダムと見なすことができる.
 
rand()は、ランダムな値を0からRAND_まで返すMAX間.RAND_MAXの範囲は少なくとも32767間(int)である.unsigned intで2バイトは65535、4バイトは4294967295の整数範囲です.0~RAND_MAXの各数字が選択される確率は同じです.
 
rand()で生成された乱数は,実行するたびに前回と同じである.異なる場合は、関数srand()で初期化します.srand(unsigned int)(time(NULL))法を用いて,異なる乱数シードを生成することができ,
プログラムを実行するたびに時間が違うからです.
 
4.乱数を生成する使い方
1)srand()にunsigned intタイプのシードを提供する.
2)srand()が呼び出され、srand()に供給されるシード値に基づいて乱数(0からRAND_MAXの間)が返される.
3)必要に応じてrand()を複数回呼び出し、新しい乱数を間欠的に得る.
4)いつでもsrand()に新しいシードを提供し,rand()の出力結果をさらに「ランダム化」することができる.
 
0~RAND_MAX間の乱数プログラム
#include
 
#include   #include  
using
 
namespace
 std; 
int
 main()
 

                srand((unsigned)time(NULL)); 
               
for(
int
 i = 0; i < 10;i++ ) 
                                cout << rand() << '\t'; 
                cout << endl; 
               
return
 0;
 
}
 
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)を使用します.
C++で0--N-1の間の乱数を生み出すとしたらどうしますか?簡単だと言えるかもしれませんが、見てください.
srand( (unsigned)time( NULL ) ); rand() % N;
よく考えてみると、この結果はランダムですか(もちろんrand()関数の擬似ランダム性は考慮しません)?
いいえ、rand()の上限はRAND_ですからMAX、一般的にはRAND_MAXはNの整数倍ではないのでRAND_MAX%=rであれば、0-r間の数値の確率は大きくなり、r+1-N-1間の数値の確率は小さくなります.また、N>RAND_MAX、どうすればいいですか?
任意の範囲の等確率乱数resultを生成できる比較的適切なスキームを以下に示す.最後にもっと簡単な方法があります.
1、N R ) t = rand();          result = t % N;//N>RAND_MAXは、セグメントサンプリングを考慮して[n/(RNAD_MAX+1)]セグメントに分け、セグメントを待ってから各セグメント内の要素を得ることができる.このようにセグメントにも同様に末尾数の問題があり、毎回整数セグメントにちょうど分けられるのではなく、一定または多かれ少なかれ1つの余剰セグメントがあり、この部分の値はどのように選択されるのか.余剰セグメントを選択したデータを取り出して選択し、まず余剰セグメントを選択した確率のイベントが発生し、その後、r=N%(RAND_MAX+1);//剰余if(happened((double)r/N)//剰余セグメントに選択された確率result=N-r+myrandom(r);//myrandomはケース1のコードでelse result=rand()+myrandom(N/(RAND_MAX+1)*(RAND_MAX+1);//残りのセグメントが選択されない場合、セグメント選択の完全なコード:#include #include #include const double MinProb=1.0/(RAND_MAX+1); bool happened(double probability)//probability 0~1 {     if(probability<=0)     { return false;     }     if(probabilitylong myrandom(long n)/0~n-1間の等確率乱数{t=0;if(n<=RAND_MAX){long R=RAND_MAX-(RAND_MAX+1)%n;//端数t=rand();while(t>r){t=rand();       }         return t % n; }else{long r=n%(RAND_MAX+1);//剰余if(happened((double)r/n)//剰余を取る確率{return n-r+myrandom(r);       }         else        {             return rand()+myrandom(n/(RAND_MAX+1))*(RAND_MAX+1);        }     } }
 
もう一つの非常に簡単な方法は
random_shuffle( RandomAccessIterator _First, RandomAccessIterator _Last ).
例えば、0-N-1の間の乱数を生成するには、このように書くことができます.
#include #include
long myrandom(long N){std::vectorvl(N);//Nサイズのvectorfor(long i=0;i       std::random_shuffle( vl.begin(), vl.end() );
       return (*vl.begin()); }
random_shuffleには3つのパラメータのリロードバージョンがあります
random_shuffle( RandomAccessIterator _First, RandomAccessIterator _Last, RandomNumberGenerator& _Rand )
3番目のパラメータは、最初の2つのパラメータ間の要素をランダム化するために、カスタム乱数ジェネレータを受け入れることができます.
この方法の欠点は,ただ1つの乱数が必要であれば,Nが大きいと空間消費が大きいことである.