C# でランダム クラスをシードする
-
C#
で乱数クラスをシードする関数を作成する -
Random()
クラスを使用してC#
でランダム クラスをシードする -
Environment.TickCount
プロパティを使用してC#
でランダム クラスをシードする -
C#
でRNGCryptoServiceProvider
クラスを使用してランダム クラスをシードする
このチュートリアルでは、アプリケーションでランダム性を実現するために C# でクラスをシードする方法について説明します。 クラスをシードする主な方法は 4つあります。すべては Random
クラスから始まり、インスタンスを初期化し、Next()
メソッドを呼び出してランダムな整数を取得することで、特定の範囲のない数値を生成できます。 NextDouble()
メソッドを使用した 10 進数。
クラスをゼロから作成できます。 Random
クラス、Environment.TickCount
、または RNGCryptoServerProvider
クラスを使用して、C# でランダム クラスをシードできます。
C#
で乱数クラスをシードする関数を作成する
public static int random_func(int _min, int _max){}
のような関数を作成し、Random
クラスからオブジェクトを作成して、min
値と max
値に対して Next()
メソッドを実行します。
Random
クラスのプライベートな静的オブジェクトに対して操作を実行するパブリック関数を保持する静的クラスを作成することで、この手法を繰り返すことができます。 真のステートレス静的メソッドの場合、Guid
に厳密に依存して、Guid.NewGuid().GetHashCode()
などで乱数を生成できます。
using System;
using System.Windows.Forms;
namespace seed_random_class {
public partial class Form1 : Form {
// function to get a random number
public static int RandomNumber(int min, int max) {
Random random = new Random();
return random.Next(min, max);
}
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {}
private void label1_Click(object sender, EventArgs e) {}
private void button1_Click(object sender, EventArgs e) {
int min = 0;
int max = 10;
int return_num;
return_num = Form1.RandomNumber(min, max);
label1.Text = return_num.ToString();
/* alternative approach
byte[] _random = new byte[6];
for (int i = 0; i < 6; ++i)
_random[i] = (byte)(Form1.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);
*/
}
}
}
出力:
Guid
の目的は一様分布ではなく一意であることであり、ほとんどの場合、ランダム性の反対であり、一様分布を実装していないことを理解することが重要です。そのため、Random
クラスに基づいて関数を作成することが有効なアプローチです。 . また、Random((int)DateTime.Now.Ticks)
のように、より大きな予測不可能な数値をランダム クラスにシードすることで、ランダム性を向上させることもできます。
Random()
クラスを使用して C#
でランダム クラスをシードする
Random
クラスのインスタンスを作成し、ループ内でそのインスタンスに Next()
メソッドを適用することは、C# でクラスをシードするための常に最良の方法です。 単一の Random
クラス インスタンスが生成する数値は、常に均一に分散されます。すべての乱数に対して新しい Random
クラス インスタンスをすばやく連続して作成することにより、同一の乱数を生成するために同じ値をシードすることができます。
完全を期すために Random
クラスを再シードし、新しいシードから新しいインスタンスを作成することをお勧めします。再シードは、予測可能性が問題になる場合に最適なオプションです。 パターン認識が攻撃者側から適用されるよりも速く再シードする必要があり、2つのジェネレーターに同じ値がシードされないようにすることができます。
new Random()
は常にシステム クロックを使用して初期化されるため、同じ値を取得できます。 したがって、単一の Random
インスタンスを保持し、同じインスタンスで Next()
メソッドを使用し続ける必要があります。
using System;
using System.Windows.Forms;
namespace seed_random_class {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {}
private void label1_Click(object sender, EventArgs e) {}
private void button1_Click(object sender, EventArgs e) {
var _random = new Random();
for (int i = 0; i < 100; ++i) label1.Text = _random.Next(1, 100).ToString();
}
}
}
出力:
最も重要なことは、シードを Next()
と同期させるために lock
が必要なことです。これは、Next()
を複数のスレッドに同時に適用すると、結果をさらにランダムにすることができるためです。 内部実装が壊れる可能性があります。 lock
はスレッドの安全性を保証し、同期は最大のランダム性を達成するための最良の方法です。
Random
クラス インスタンスで lock
を使用することも代替手段ですが、他の方法よりもスレッド セーフではありません。 Random
オブジェクトのスレッドとパラメーターなしのコンストラクターを使用しているとします。
その場合、Thread.Sleep
メソッドの呼び出しによって引き起こされる遅延に直面する可能性があり、そのオブジェクトに対して異なるシード値が生成され、異なるシーケンスの乱数が生成される可能性があります。
Environment.TickCount
プロパティを使用して C#
でランダム クラスをシードする
System
名前空間に属し、システムが起動してからのミリ秒数を取得することが重要であり、32 ビットの符号付き整数を表します。 このプロパティは、Int32.MinValue
と Int32.MaxValue
の間を循環し、それぞれ負の数と正の数を表します。符号ビットを削除して、24.9
日ごとに 0 と最大の正の値の間を循環する非負の数を生成できます。 .
その 32 ビット符号付き整数の解像度は、システム タイマーの範囲の 10 ~ 16 ミリ秒の解像度に制限されます。 最も重要なのは、System.Random
で使用される実装が Environment.TickCount
であり、DateTime.UtcNow.Ticks
をキャストする必要がなく、C# アプリケーション全体で乱数クラスのシードの再利用が容易になることです。
using System;
using System.Threading; // essential namespace for threading
using System.Windows.Forms;
namespace seed_random_class {
public static class StaticRandom {
// initialize the seed
private static int _var_seed;
// a thread-safe approach to access the random class via seed
// `<Random>` implies the Random class
private static ThreadLocal<Random> local_thread =
new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref _var_seed)));
// method that utilizes the `Environment.TickCount` property
static StaticRandom() {
_var_seed = Environment.TickCount;
}
public static Random class_inst {
get { return local_thread.Value; }
}
}
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {}
private void label1_Click(object sender, EventArgs e) {}
private void button1_Click(object sender, EventArgs e) {
label1.Text = StaticRandom.class_inst.Next(1, 100).ToString();
}
}
}
出力:
C#
で RNGCryptoServiceProvider
クラスを使用してランダム クラスをシードする
いくつかの特殊なケースでは、RNGCryptoServerProver
クラスの使用が必要になります。 System.Security.Cryptography
名前空間に属し、CSP (Cryptographic Service Provider) によって提供される実装を使用して暗号化 RNG (乱数ジェネレーター) を実装し、継承することはできません。
IDisposable
インターフェイスを実装し、try/catch
ブロックで Dispose
メソッドを呼び出すことができるため、直接的または間接的に破棄することが重要です。 C# では、using
コンストラクトを使用して破棄し、ランダム クラスの完全なシードを作成できます。
System.Security.Cryptography.RNGCryptoServiceProvider
クラスはスレッド セーフであり、既知のシードから値を再現することで真のニーズに応えます。 ただし、2つの独立した値を生成できる関数を作成することは数学的に不可能であり、これは暗号化スキームが完全に安全ではないことも意味し、使用するためのコストが高すぎる場合もあります。
using System;
using System.Windows.Forms;
namespace seed_random_class {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {}
private void label1_Click(object sender, EventArgs e) {}
private void button1_Click(object sender, EventArgs e) {
byte[] foo = { 0x32, 0x00, 0x1E, 0x00 };
System.Security.Cryptography.RNGCryptoServiceProvider prov =
new System.Security.Cryptography.RNGCryptoServiceProvider();
prov.GetBytes(foo);
}
}
}
出力:
Next(int)
または Next(int min, int max)
メソッドを使用して範囲内の乱数を生成するか、Next()
および NextBytes()
を使用してそれぞれランダムな整数と系列を生成できます バイト値の。 コンストラクターのオーバーロードを介してシードを提供するか、フレームワークがこれを処理します。
Random
クラスをインスタンス化するのはコストのかかる方法であり、やりすぎると C# アプリケーションのパフォーマンスが低下する可能性があります。 代わりに、単一の Random
インスタンスをインスタンス化し、Next()
メソッドを複数回呼び出します。 暗号化は、C# でランダム クラスをシードするためのより安全で保護的なアプローチです。
Hassan is a Software Engineer with a well-developed set of programming skills. He uses his knowledge and writing capabilities to produce interesting-to-read technical articles.
GitHub