擬似乱数の生成アルゴリズムにはいくつか種類がありますが、Randomクラスを継承して独自に疑似乱数を実装することもできます。 Randomクラスを継承して疑似乱数生成アルゴリズムを実装する際に最低限必要となるのは、Sampleメソッドをオーバーライドし、0.0以上1.0未満の乱数を返すように実装することです。
以下の例では、線形合同法を実装したLCGRandomクラスを作成し、Randomクラスが生成する乱数との比較を行っています。 なお、この実装は一つの例として挙げたもので、生成される乱数の周期や分散については考慮していません。 実際に使用する場合は注意してください。
以下のコードでは、Sampleメソッドでオーバーフローが発生するため、/removeintchecks+
オプションを有効にしてコンパイルするか、プロジェクトファイルにてRemoveIntegerChecks
をTrue
にしてコンパイルしないと例外OverflowExceptionがスローされます。
' vbc /removeintchecks+
' dotnet build -p:RemoveIntegerChecks=True
Imports System
' 線形合同法による疑似乱数の生成を実装したクラス
Class LCGRandom
Inherits Random
Private x As Long
Private Const a As Long = 1140671485
Private Const c As Long = 12820163
Public Sub New()
Me.New(Environment.TickCount) ' Environment.TickCountの値をデフォルトのシード値として使用する
End Sub
Public Sub New(ByVal seed As Integer)
x = seed
End Sub
Protected Overrides Function Sample() As Double
x = (a * x + c) And Long.MaxValue
Return CDbl(x) / Long.MaxValue
End Function
End Class
Class Sample
Shared Sub Main()
Dim rand As New Random(0)
Dim lcg As New LCGRandom(0)
Const format As String = "{0,-6} {1,-6}"
Console.WriteLine(
format,
NameOf(rand),
NameOf(lcg)
)
For i As Integer = 1 To 15
Console.WriteLine(
format,
rand.Next(0, 100),
lcg.Next(0, 100)
)
Next
End Sub
End Class
rand lcg 72 0 81 0 76 97 55 2 20 65 55 93 90 23 44 65 97 44 27 61 29 37 46 18 63 78 46 82 98 28
この例ではオーバーフロー時に例外のスローを抑止する目的でunchecked
ステートメント、および/removeintchecks+
コンパイルオプションを使用しています。 詳しくは整数型のオーバーフローとチェックを参照してください。
このように、Sampleメソッドをオーバーライドすることで独自の乱数生成を行うことができます。 場合によっては、Sampleメソッドを適切に実装することでメソッドの戻り値の範囲が閉区間となるようにすることもできます。
なお、Randomクラスを継承する場合、引数をとらないNextメソッドなどSample以外のメソッドもオーバーライドしないと動作が変わらないメソッドがあります。 詳しくはSampleメソッドのリファレンスを参照してください。