web-dev-qa-db-ja.com

Random.Next()が常に同じ数を返すのはなぜですか

この方法を検討してください:

private static int GenerateRandomNumber(int seed, int max)
{
   return new Random(seed).Next(max);
}

私のマシンでは、このループを実行すると、1500回の繰り返しで同じ数が得られます。

  for (int i = 0; i < 1501; i++)
            {
                int random = GenerateRandomNumber(100000000, 999999999);
                Console.WriteLine(random.ToString());
                Console.ReadKey();
            }

反復ごとに145156561を取得します。

私は差し迫った問題はありません。Next(max)が「非負の値を返すランダム指定された最大値未満の数値を返します。おそらく基本的なことを理解していないので、この動作に興味を持っていました。 。

20
Ta01

常に同じシードで新しいインスタンスをシードしてから、最初の最大値を取得します。シードを使用することで、同じ結果が保証されます。

異なる結果をもたらす静的な乱数生成が必要な場合は、これを少し修正する必要があります。ただし、ランダムはスレッドセーフではないため、静的に使用する場合はある程度の同期が必要です。何かのようなもの:

private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
     random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
     lock(syncObj)
     {
         if (random == null)
             random = new Random(); // Or exception...
         return random.Next(max);
     }
}
40
Reed Copsey

ディルバートは2001年に同じ問題に遭遇しました。

http://dilbert.com/strips/comic/2001-10-25/

一致?

そうは思いません。

そして、random.orgは同意します: http://www.random.org/analysis/

7
dbrin

問題は、毎回同じシード番号で新しいRandomインスタンスを作成していることです。単一のRandomインスタンスを作成し(必要に応じて静的に保存し)、同じインスタンスで次のメソッドを呼び出すだけです。

乱数の生成は真にランダムではありません。詳細は このWikipediaのエントリ を参照してください。

6
Eric Giguere

疑似乱数ジェネレータは通常、シードを選択し、そのシードに基づいて決定論的シーケンスを生成することによって機能します。毎回同じシードを選択すると、同じシーケンスが生成されます。

.NETには「唯一」の2 ^ 32種類のランダムシーケンスがあります。

3
Jens

内部の仕組みがわからない.. wikiで確認してください。しかし、それは非常に簡単です。

public class MathCalculations
{
    private Random rnd = new Random();

    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

number1、Number2、Number3、Number4、Number5、Number6を生成します(1つのシード、多数の数値の1つのシーケンス、ランダム*実際にはありませんが、おおよそ*)

ただし、これを行う場合:

public class MathCalculations
{
    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {  
        Random rnd = new Random();
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

ここで、Number1、Number1、Number1、Number1、Number1、Number1(1つのシード、多数の数値からなる6つの等しいシーケンス、常にそれぞれの等しいシーケンスから同じ開始番号を選択します)を取得します。ある時点で、Number1は異なります。時間の経過とともに変化しますが、これを待つ必要があります。それでも、シーケンスからnumber2を選択することはありません。

その理由は、同じシードで新しいシーケンスを生成するたびに、シーケンスは何度も同じであり、ランダムに生成されるたびに、そのシーケンスの最初の数が選択されるためです。もちろん常に同じです。

これが乱数発生器の基礎となるメソッドによって技術的に正しいかどうかはわかりませんが、それが動作です。

2
user957537

誰もが「迅速かつ汚い」「解決策」を探している場合(そして私はその用語を慎重に使用しています)、ほとんどの場合これで十分です。

int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random Rand = new Random(secondsSinceMidnight); 
var usuallyRandomId = Rand.Next();

通常はランダムに使用することに注意してください。回答としてマークされたアイテムは、これを行うためのより正しい方法であることに同意します。

0
AnthonyJ

すべてにサラム、まあそれは私も夢中にさせた。答えは簡単です。ランダムを生成する前にシードを変更してください。

例:1から10までの乱数を生成したい

Random rnd = new Random(DateTime.Now.Seconds);
int random_number = rnd.Next(10);

ループの中に入れて3回実行します。 10未満の乱数が出力されます。

0
Talha