なぜこのメソッドは毎回同じランダム文字列を返すのですか?
質問
作業中の別のプロジェクトをテストするには、一意の行のブロックを作成する必要があります。
だから、Xの長さのランダムな文字列を生成する簡単なプログラムを作成しました。
問題は、一度呼び出すとランダムな文字列を取得し、再度呼び出すと(たとえばforループで)ループの実行全体で同じ文字列を取得することです。
キャッシュされているなどの感覚がありますが、.netがそれを実行したことを知らなかったため、この時点で混乱しています。
呼び出しコード:
StreamWriter SW = new StreamWriter("c:\\test.txt");
int x = 100;
while (x >0)
{
SW.WriteLine(RandomString(20));
x--;
}
方法は次のとおりです:
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i <= Length; ++i)
{
int x = randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
出力は次のとおりです:
"VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
..................
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB"
では、Random.next()が常に新しい乱数を返すと思ったのはなぜですか?
解決
時間内に近すぎるRandom
インスタンスを作成しています。各インスタンスはシステムクロックを使用して初期化され、クロックが変更されていないため、同じ乱数のシーケンスが繰り返し取得されます。
using
クラスの単一のインスタンスを作成し、繰り返し使用します。
StreamWriter
キーワードを使用して、完了したらfor
を閉じて破棄します。 length
キーワードを使用すると、ループのコードを簡単に認識できます。
using (StreamWriter SW = new StreamWriter("c:\\test.txt")) {
Random rnd = new Random();
for (int x = 100; x > 0; x--) {
SW.WriteLine(RandomString(rnd, 20));
}
}
このメソッドは、パラメーターとして<=>オブジェクトを受け取ります。
また、長さを使用してStringBuilderを正しい容量で初期化し、ループ中に再割り当てする必要がないようにします。 <!> lt;を使用します。ループでは<!> lt; =の代わりに演算子を使用します。そうでない場合は、<=>パラメーターが指定する文字数より1文字長い文字列を作成します。
private static string RandomString(Random rnd, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int x = rnd.Next(65, 122);
sb.Append((char)x);
}
return sb.ToString();
}
他のヒント
MSNのランダムコンストラクターの説明を参照してください。 p>
デフォルトのシード値は システムクロックと有限 解決。その結果、異なる で作成されるランダムオブジェクト への呼び出しによる密接な継承 デフォルトのコンストラクタは 同一のデフォルトのシード値、および したがって、同一のセットを生成します 乱数の
したがって、プログラムの先頭でRandom()コンストラクターを1回だけ呼び出すか、Random(int32)コンストラクターを使用して、さまざまなシードを自分で定義します。
各呼び出しで新しいRandomオブジェクトを作成するため。
randomNumberをメソッドから単純に移動し、クラスメンバーにします。
private Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
//...
}
すべてのソフトウェアランダムジェネレーターは「疑似ランダム」であり、(開始)シードに基づいて一連の数値を生成します。同じシードを使用すると、同じシーケンスが生成されます。時々これは便利です。各実行で同じシーケンスを生成するプログラムを生成する場合は、new Random(0)
を使用できます。
編集:.Net Randomクラスは自動シードであるようですが、私はそれを知りませんでした。他の人が指摘しているように、それはタイミングの問題です。
randomNumberを一度だけ宣言する
public class MyClass
{
private static Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i ... Length; ++i)
{
int x = MyClass.randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
}
同様の質問、多くの回答:
時間が短いため、乱数のシードはすべて同じです。実際、毎回同じシードを使用してランダムジェネレーターを再作成するため、Next()呼び出しは同じランダム値を返します。