C言語で重複しない任意の数の乱数を生成

C言語

アルゴリズムの勉強をしていると、ソートプログラムなどで大量の乱数データが必要な場合があります。

この記事では、C言語で重複しない任意の数の乱数を生成する方法について紹介します。

乱数の取得方法

C言語で乱数を生成する場合には「rand」関数を使用します。

「rand」関数で取得した値に対して取得したい乱数のレンジで割った余りを乱数として使用します。

// 0~99の間の乱数を取得
int rnd = rand() % 100;

最小値が0以外の場合には、レンジで割った余りに最小値を加算します。

// 最小値
int min = 50;
// レンジ
int range = 50;
// 50~99の間の乱数を取得
int rnd = rand() % range + min;

乱数シードの初期化

上記のプログラムは乱数と言いながらも実は何回実行しても同じ値となってしまいます。

「乱数シード」と呼ばれる乱数を生成する際の種が未初期化のため、常に同じ値から乱数が生成されるために同じ値になってしまっています。

乱数シードの初期化を行うためには「srand」関数に一意な値を渡します。 一般的には「時間」は一意なため、「time」関数の実行結果を渡します。

// 乱数シードの初期化
srand((unsigned)time(NULL));

この処理はプログラム中で一度だけ実施されればよいので、変数宣言の直後にでも実施しておけば実行するたびに異なる値を取得できるようになります。

重複しない任意の数の乱数を生成

乱数の取得方法がわかったところで、重複しない任意の数の乱数を生成する方法について紹介します。

main関数、変数の準備、初期化処理

まず初めにmain関数の準備をしていきます。

使用する変数の宣言や初期化処理を記述していきます。

#include <stdio.h>
#include <time.h>

// データ数
#define N 100

int main()
{
    // 最小値、レンジ
    int min = 0, range = 100;
    // データ
    int data[N] = { 0 };
    // ループ変数
    int i, j;

    // 乱数シード初期化
    srand((unsigned)time(NULL));

    // 以降に処理を記述

    return 0;
}

変数をたくさん宣言しましたが、それぞれ以下の用途で使用します。

最小値、レンジ乱数生成で使用
データ生成されるデータ格納
ループ変数データ生成ループインデックス

乱数を生成

続いてforループを使用してデータ数分乱数を生成します。

#include <stdio.h>
#include <time.h>

// データ数
#define N 100

int main()
{
    // 最小値、レンジ
    int min = 0, range = 100;
    // データ
    int data[N] = { 0 };
    // ループ変数
    int i, j;

    // 乱数シード初期化
    srand((unsigned)time(NULL));

    // データ生成
    for (i = 0; i < N; i++)
    {
        // 乱数生成
        data[i] = rand() % range + min;
    }

    return 0;
}

前の章で紹介した乱数生成処理をforループの中で実施しているだけです。

重複を気にしないのであればこの時点でプログラムは完成です。

生成した乱数が重複しないようにする

最後に生成した乱数が重複しないよう修正をしていきます。

考え方はとても簡単で、乱数を生成した際にそれまで生成したデータとの比較を行いデータに含まれている場合には再度乱数を生成するようにします。

#include <stdio.h>
#include <time.h>

// データ数
#define N 100

int main()
{
    // 最小値、レンジ
    int min = 0, range = 100;
    // データ
    int data[N] = { 0 };
    // ループ変数
    int i, j;

    // 乱数シード初期化
    srand((unsigned)time(NULL));

    // データ生成
    for (i = 0; i < N; i++)
    {
        // 重複チェック
        do
        {
            // 乱数生成
            data[i] = rand() % range + min;
            // 生成済みデータと比較
            for (j = 0; j < i; j++)
            {
                // 生成済みデータに含まれる場合再度乱数生成
                if (data[i] == data[j]) break;
            }
        } while (i != j);
    }

    return 0;
}

上記のプログラムで生成されたdataを出力すると以下のように重複のない乱数データを取得することができます。
(もちろん実行ごとに実行結果は変わります)

97 49 73 48 60  5 61 45 28 66
95 22 46 44 25 63 70 39  9 33
24 13 72 14  4  0 53 74 54 35
78 15 32 59 81 82  6 55 80  7
77 84 40 93 87 17 83 37 11 98
31 50 26 16 58 27 30 57  2 47
86 51 71 89 68 34 79 56 85 36
29 38 69  1 10 21 62 43 91 96
99 88 75 12 76 90 19 92 41 64
94 65 18 23  8 20 42 67 52  3

重複のない乱数を生成する際の注意点

上記でプログラムの作成は完了ですが、重複のない乱数を生成する場合には「データ数」より「レンジ」が必ず多く(または同数に)なるように注意してください。

「レンジ」よりも「データ数」が多くなってしまうと必ず重複が発生することになるため、処理の都合上無限ループになってしまいます。

終わりに

C言語で重複しない任意の数の乱数を生成する方法について紹介しました。

プログラミングやアルゴリズムの勉強をしている方にとっては乱数データの生成は必須なので、この記事で紹介されている方法でデータの生成を試してみてください。

この記事について誤っている点・不明な点などありましたらコメントまでお願いします。

コメント

タイトルとURLをコピーしました