DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

乱数を生成する

乱数を生成するには、Randomクラス(System名前空間)を使います。RandomクラスはDonald E. Knuth の乱数ジェネレータ減算アルゴリズムに基づいており、疑似乱数を生成します。

Randomクラスはシード値が分かってしまうと生成される乱数が予測できます。よって、厳密な乱数が必要なケースで使用するのは危険です。

以下にRandomクラスを使って乱数を生成するいくつかの例を示します。

VB.NET
コードを隠すコードを選択
'シード値(1000)を使用して初期化 
'シード値が変わらなければ毎回同じ乱数を返す 
Dim r As New System.Random(1000)
'シード値を指定しないとシード値として Environment.TickCount が使用される 
'Dim r As New System.Random()

'0以上10未満の乱数を整数で返す 
Dim i1 As Integer = r.Next(10)

'-10以上10未満の乱数を整数で返す 
Dim i2 As Integer = r.Next(-10, 10)

'0以上Int32.MaxValue未満の乱数を整数で返す
Dim i3 As Integer = r.Next()

'バイト配列の要素に乱数を入れる 
Dim bs As Byte() = New Byte(7) {}
r.NextBytes(bs)

'0.0以上1.0未満の乱数を倍精度浮動小数点数で返す 
Dim d As Double = r.NextDouble()
C#
コードを隠すコードを選択
//シード値(1000)を使用して初期化
//シード値が変わらなければ毎回同じ乱数を返す
System.Random r = new System.Random(1000);
//シード値を指定しないとシード値として Environment.TickCount が使用される
//System.Random r = new System.Random();

//0以上10未満の乱数を整数で返す
int i1 = r.Next(10);

//-10以上10未満の乱数を整数で返す
int i2 = r.Next(-10, 10);

//0以上Int32.MaxValue未満の乱数を整数で返す
int i3 = r.Next();

//バイト配列の要素に乱数を入れる
byte[] bs = new byte[8];
r.NextBytes(bs);

//0.0以上1.0未満の乱数を倍精度浮動小数点数で返す
Double d = r.NextDouble();
補足:.NET Framework 2.0以降では、NextDoubleメソッドは、Next()メソッド(パラメータなし)に 4.6566128752457969E-10 を掛けた値を返します(正確にはパタメータのないNextメソッドではなく、privateメソッドのInternalSampleメソッドです)。パラメータを1つ持つNextメソッドは、NextDoubleメソッドの結果を使って計算されています(正確にはNextDoubleメソッドではなく、protectedメソッドのSampleメソッドです)。パラメータを2つ持つNextメソッドは、Next()またはNextDoubleメソッドの結果を使って計算されています。NextBytesメソッドは、Next()メソッドの結果を使って計算されています。.NET 1.1以前では、NextDoubleメソッドの結果を使ってすべてのNextメソッドとNextBytesメソッドが計算されています。

厳密なランダムバイトを作成する

暗号化に使用する厳密なランダムバイトを作成するには、RNGCryptoServiceProviderクラスのGetBytesメソッドを使用します。

この方法はRandomクラスを使用した方法と比べ、かなり遅いです。よって、ケースバイケースで使い分けてください。

VB.NET
コードを隠すコードを選択
'暗号化に使用する厳密なランダムバイトを作成する
'100バイト長のバイト型配列を作成
Dim random() As Byte = New Byte(100) {}

'RNGCryptoServiceProviderクラスのインスタンスを作成
Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()
'または、次のようにもできる
'Dim rng As System.Security.Cryptography.RandomNumberGenerator = _
'    System.Security.Cryptography.RandomNumberGenerator.Create()

'バイト配列に暗号化に使用する厳密な値のランダムシーケンスを設定
rng.GetBytes(random)

'バイト配列に暗号化に使用する厳密な0以外の値の
'ランダムシーケンスを設定するには次のようにする
'rng.GetNonZeroBytes(random)
C#
コードを隠すコードを選択
//暗号化に使用する厳密なランダムバイトを作成する
//100バイト長のバイト型配列を作成
byte[] random = new byte[100];

//RNGCryptoServiceProviderクラスのインスタンスを作成
System.Security.Cryptography.RNGCryptoServiceProvider rng =
    new System.Security.Cryptography.RNGCryptoServiceProvider();
//または、次のようにもできる
//System.Security.Cryptography.RandomNumberGenerator rng =
//    System.Security.Cryptography.RandomNumberGenerator.Create();

//バイト配列に暗号化に使用する厳密な値のランダムシーケンスを設定
rng.GetBytes(random);

//バイト配列に暗号化に使用する厳密な0以外の値の
//ランダムシーケンスを設定するには次のようにする
//rng.GetNonZeroBytes(random);

RNGCryptoServiceProviderクラスでランダムな数値を取得する

RNGCryptoServiceProviderクラスのGetBytesメソッドではByte型の配列を取得できますが、例えばInt32型やInt64型のランダムな数値で取得するには、Byte型配列をBitConverterクラスで変換します。

Int32型のランダムな値を取得する例を以下に示します。ランダムな値は、Int32.MinValue以上Int32.MaxValue以下のいずれかの値になります。

VB.NET
コードを隠すコードを選択
'Int32と同じサイズのバイト配列にランダムな値を設定する
Dim bs As Byte() = New Byte(3) {}
Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()
rng.GetBytes(bs)

'Int32に変換する
Dim i As Integer = System.BitConverter.ToInt32(bs, 0)
C#
コードを隠すコードを選択
//Int32と同じサイズのバイト配列にランダムな値を設定する
//byte[] bs = new byte[sizeof(int)];
byte[] bs = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng =
    new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bs);

//Int32に変換する
int i = System.BitConverter.ToInt32(bs, 0);
補足:このようにランダムな整数を生成する方法を使って、0以上ある数未満のランダムな整数を生成する簡単な方法は、生成した整数とある数を割った余りの絶対値を計算することです。例えば0以上10未満のランダムな整数を生成したいならば、上記の例のようにInt32型のランダムな値を生成した後に(この値を「i」とする)、VB.NETならば「Math.Abs(i Mod 10)」、C#ならば「Math.Abs(i % 10)」とします。

なおRandomクラスの場合は、NextBytesメソッドでランダムなバイト配列の値を取得できますので、同じ方法が使えます。

  • 履歴:
  • 2009/9/9 説明を追加。
  • 2010/7/22 「RNGCryptoServiceProviderクラスでランダムな数値を取得する」を追加。Randomクラスに関する補足を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。