C# random クラスで乱数を取得する

C# サンプルコード プログラミング

概要説明

RandomクラスのNextメソッドで整数の乱数が取得できます。

Nextメソッドの引数で以下のように取得できます。

Next()0 以上の乱数を取得する
Next(Int32)指定した最大値より小さい 0 以上の乱数を取得する
Next(Int32, Int32)指定した範囲内の乱数を取得する

ただ・・・

RandomクラスをNEWするときに、シード値を渡さなくてもインスタンスできるけど

複数同時にインスタンスが作られた時に、同じ乱数が生成されることがあるみたいです。

なので、同時に乱数を作るときには同じシード値を渡さないように注意が必要です。

 

それと・・・

microsoftのドキュメントを見ると注釈があり

「擬似乱数は、少数の数値から等しい確率で選択されます。 選択した数値は、数学的アルゴリズムを使用して選択するため、完全にはランダムではありませんが、実用的な目的では十分にランダムです。 」とあります。

 

うーん、注釈の続きで・・・

「ランダムなパスワードの作成に適したランダムな値など、暗号的に安全な乱数を生成するには、クラスを使用する RNGCryptoServiceProvider か、からクラスを派生させ System.Security.Cryptography.RandomNumberGenerator ます。」とあります。

microsoft ドキュメント Random クラス

 

暗号化などに使う厳密な乱数に使うのでなければ、Randomクラス

暗号化などの厳密な乱数が必要なら、RNGCryptoServiceProviderクラスを使ってね

みたいです。(RNGCryptoServiceProviderクラスは処理が重い見たいです。)

 

ただ、整数の範囲を指定できるRandomクラスは使い勝手が良いので、RNGCryptoServiceProviderクラスで乱数を作成し、その値をシード値に使ってRandomクラスをNEWするのが良いかと思います。

 

Randomクラスだけを使ったサンプルとRNGCryptoServiceProviderクラスを組み合わせたサンプルを以下に作成しました。

プログラミング

言語:C#

/// <summary>
/// 疑似乱数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
    // シード値用の値
    int s = 0;

    // Randomクラス
    Random random1 = new System.Random(s++);
    Random random2 = new System.Random(s++);
    Random random3 = new System.Random(s++);

    // 0 以上の乱数を取得する
    int rand1 = random1.Next();
    Console.WriteLine($"0 以上のランダムな整数 : {rand1} ");

    // 指定した最大値より小さい 0 以上の乱数を取得する
    int rand2 = random2.Next(50);
    Console.WriteLine($"指定した最大値より小さい 0 以上のランダムな整数 : {rand2} ");

    // 指定した範囲内の乱数を取得する
    int rand3 = random3.Next(1, 50);
    Console.WriteLine($"指定した範囲内のランダムな整数 : {rand3} ");
}

/// <summary>
/// RNGCryptoServiceProviderを使用した乱数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{

    for (int i = 0; i < 3; i++)
    {
        // RNGCryptoServiceProviderクラス
        RNGCryptoServiceProvider rNGCryptoServiceProvider = new RNGCryptoServiceProvider();

        // 暗号乱数を格納するbyte配列(32ビット分)
        byte[] cryptRand = new byte[4];

        // 暗号乱数を取得する
        rNGCryptoServiceProvider.GetBytes(cryptRand);

        // 暗号乱数をbyte配列から整数に変換する
        int s = System.BitConverter.ToInt32(cryptRand, 0);

        // RNGCryptoServiceProviderクラスのシード値に暗号乱数を渡しインスタンス化する
        Random random = new System.Random(s);

        // 1~100の乱数を取得する
        int rand = random.Next(1, 100);

        Console.WriteLine($"指定した範囲内のランダムな整数 : {rand} ");
    }
}

実行結果

Randomクラスだけを使ったサンプルの結果

ちゃんと乱数出来てますね。

・RNGCryptoServiceProviderクラスを組み合わせたサンプルの結果

こちらも見た目では厳密かわかりませんが、できてますね!

より厳密な乱数・・・とか出てきて、乱数は結構奥が深そうな感じです。

コメント

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