1. ホーム
  2. C++

C/C++ におけるランダム関数 rand() および srand() の使用法

2022-02-14 08:24:34

i. rand()

<テーブル 機能名 ランド   機能 乱数発生器 使用方法 int rand(void);  ヘッダーファイル stdlib.h 関数の説明 rand()の内部実装は線形合同を使って行われています。これは本当の乱数ではありませんが、例外的に周期が長いため、ある範囲内では乱数と見なすことができます。 rand() は 0 から RAND_MAX までの範囲の乱数値を返す。RAND_MAX の範囲は少なくとも 32767 (int) の間である。unsigned int double bytesを使用すると65535、quad bytesを使用すると4294967295の整数範囲になります。0からRAND_MAXの各数値は、選択される確率が等しくなります。 ユーザーが乱数種を設定しない場合、システムのデフォルトは1の乱数種になります。 rand()は疑似乱数を生成し、実行するたびに同じ乱数になります。異なる乱数にする場合は、srand()関数で初期化します。

  プログラム例です。

#include <iostream> 
using namespace std; 
#include <stdlib.h> 
#include <time.h> 
#define MIN 1 // range for random number generation 
#define MAX 10 
int main() 
{ 
    int i; 
    srand((unsigned)time(0)); 
    cout<<"Ten random numbers from "<<MIN<< " to "<<MAX<<" :/n"<<<endl; 

    for(i=0; i<10; i++) //generate random number 
    { 
        cout<<MIN + (int)MAX * rand() / (RAND_MAX + 1)<<"/t"; 
    } 

    cout<<endl; 
    return 0; 
} 

II. srand()

<テーブル 機能名 スランド 機能 乱数発生器の初期化 使用方法 void srand(unsigned int seed);  ヘッダーファイル stdlib.h   関数の説明 srand()は、rand()で乱数を生成する際に、乱数の種を設定するために使用します。 引数seedは整数でなければならず、通常time(0)の戻り値またはNULLを用いてseedとして使用することができる。 各シードに同じ値を設定すると、rand()で生成される乱数値は毎回同じになります。

  プログラム例です。 


#include <iostream> 
using namespace std; 
#include <stdlib.h> 
#include <time.h> 
#define MIN 0 // range for random number generation 
#define MAX 99 
int main() 
{ 
    int i; 
    srand((unsigned)time(NULL)); 
    cout<<"Ten random numbers from "<<MIN<< " to "<<MAX<<" :/n"<<<endl; 
    for(i=0; i<10; i++) //generate random number 
    { 
        cout<<MIN + rand() % (MAX + MIN - 1)<<"/t"; 
    } 
    cout<<endl; 
    return 0; 
} 

III. rand() と srand() の関係

      rand()とsrand()を併用し、srand()で乱数種の初期化、rand()で乱数の発生を行う。

      デフォルトでは乱数種は1であり、同じ乱数種は同じ乱数を生成し、ランダム性の意味を失うので、毎回異なる乱数を得るために、乱数種を初期化するために関数srand()を使用します。 srand()の引数は、時間関数値(つまり、現在の時間)を使用して、ランダム性を保証するようにrand()関数を呼び出す二つの時間は通常異なるため、です。

IV. ある範囲の乱数を生成するための一般的な表現式

      a,b) のランダムな整数を得るには、(rand() % (b-a)) を使用します。+ a (結果値には b のない a が含まれます)。
      a,b] のランダムな整数を得るには、(rand() % (b-a+1)) を使用します。+ a (結果値には a と b の両方が含まれる)。
      (a,b] のランダムな整数を得るには、(rand() % (b-a)) を使用します。+ a + 1 (結果値はaを含まず、bを含む)。

      (要約すると、一般的な式:a + rand() % n; ここで、aは開始値、nは整数の範囲)

      a と b の間のランダムな整数を得るには、別の表現として a + (int)b * rand() / (RAND_MAX + 1) を使用します。

      0から1までの浮動小数点数を得るには、rand() / double(RAND_MAX)を使用します。

V. 同じ乱数を生成する理由

      コンピュータ乱数は擬似乱数から生成されます。つまり、M個の小さな多項式列から生成され、それぞれの小さな列は初期値であるランダムシードで生成されます。(なお、小M多項式列の周期は65535であり、乱数種を用いて乱数を生成するたびに周期は65535となり、65535個の乱数を取得すると再び出現する)。  

      rand()関数で乱数を生成できることは知っていますが、これは本当の意味での乱数ではなく、疑似乱数、つまり何らかの再帰的な式で射影した数値(シードと呼ぶこともできます)を基にした数値の系列で、この系列が大きいときは通常の発表と一致するので乱数の生成に相当しますが、本当の乱数ではなく、コンピューターの電源を普通に入れると、システムを破壊しない限りこのシードの値は固定されるのです。 

             プログラム例です。

#include <iostream> 
using namespace std; 
#include <stdlib.h> 
#include <time.h> 
int main() 
{ 
    int i; 
    for (i=0; i<10; i++) //generate 10 random numbers 
    { 
        cout<<rand()<<"/t"; 
    } 
    cout<<endl; 
    return 0; 
}

             どの実行でも同じ乱数列が得られる。

<ブロッククオート

41 18467 6334 26500 19169 15724 11478 29358 26962 24464

      異なる乱数列を得るには、このシードの値を変更する必要があります。方法:乱数生成を始める前に一度 srand(time(NULL)) を呼び出します(注意:srand() はループの外かループ呼び出しの外に置く必要があります、さもなければ同じ乱数が得られます)。

             プログラム例です。

#include <iostream> 
using namespace std; 
#include <stdlib.h> 
#include <time.h> 
int main() 
{ 
    int i; 
    srand((unsigned)time(NULL)); //initialize the random number seed 
    for (i=0; i<10; i++) //generate 10 random numbers 
    { 
        cout<<rand()<<"/t"; 
    } 
    cout<<endl; 
    return 0; 
}      


            実行するたびに、異なるランダムな配列が得られる。

1294 18562 14141 18165 11910 29784 11070 13225 131 24405
1774 25714 18734 16528 20825 17189 9848 8899 2503 5375