-2

C#ConsoleAppで、指定した可能性パラメーターに基づいてtrueまたはfalseを返すメソッドを作成しました。したがって、5を指定すると、50%がtrueになります。falseの場合も同様です。 9の場合、90%の確率で真になり、10%の確率で偽になります。ここにそれがあります:(私はこれをチュートリアルとして書いていました、そして私はそれを明確にするためにそのballs-ThatGotNumbers-inside-a-boxのような方法でそれを説明していました、それ故に変数BallNumberの名前)

static public bool TrueOrFalse(int possiblity)
{
      Random rand = new Random();
      int BallNumber = rand.Next(0, 10); // BallNumber values are from the interval: [0, 10[  (0, 1, 2, ....9)
      if (possiblity <= 0)
        return false;
      if (possiblity == 1)
        return (BallNumber == 0); // any number you like.
      if (possiblity == 2)
        return (BallNumber == 0 || BallNumber == 1); // any two numbers, cuz there's a 20% chance that you might get a ball from the box that has either number n OR m.
      if (possiblity == 3)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2); // any three numbers ... etc you got the point.
      if (possiblity == 4)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3);
      if (possiblity == 5)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3 || BallNumber == 4);
      if (possiblity == 6)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3 || BallNumber == 4 || BallNumber == 5);
      if (possiblity == 7)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3 || BallNumber == 4 || BallNumber == 5 || BallNumber == 6);
      if (possiblity == 8)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3 || BallNumber == 4 || BallNumber == 5 || BallNumber == 6 || BallNumber == 7);
      if (possiblity == 9)
        return (BallNumber == 0 || BallNumber == 1 || BallNumber == 2 || BallNumber == 3 || BallNumber == 4 || BallNumber == 5 || BallNumber == 6 || BallNumber == 7 || BallNumber == 8);

      return true; // if you give it a number higher than 10, it will return true ..
}

現在、この方法は正常に機能していますが、それを証明したかったのです。だから私はこのアイデアを思いついた:

int TruePossiblity = 0, FalsePossiblity = 0;
for (int i = 0; i < 100; i++)
{
  bool _TRUE = TrueOrFalse(5);
  if (_TRUE) TruePossiblity  += 1;
  else FalsePossiblity  += 1;
}
Console.WriteLine(x);
Console.WriteLine(y);

ここで、印刷する必要があるのは次のとおりです。

50
50

問題は、それが次のいずれかを出力することです。

100
0

また

0
100

それで、私はそれをデバッグし、それを段階的に歩き、そしてそれが実際に最終的に印刷されたことに驚いた。

50
50

System.Threading.Thread.Sleep(1); 変数を割り当てた直後に挿入する_TRUE と、より良い結果が得られましたが、それほど良くはありません。時間を長くすればするほど、より良い結果が得られます(印刷する結果に近い、50,50)。200ミリ秒を使用したとき、実際に必要な結果が50,50になりました。

現在、実行中のスレッドは1つだけで、これがメインスレッドであるため、スレッド間で競合が発生することはなく、混乱して望ましくない結果が生じる可能性があります。

何が起こっているのですか?誰かがそれを説明できますか?スリープの使用を避けることはできますか?

あなたが提供するどんなヒントにも感謝します。

4

1 に答える 1

4

Randomインスタンスには現在の時刻がシードされます。ループの実行速度が速すぎるため、同じ時間を使用します。したがって、常に同じ「ランダム」値を取得します。

メソッド自体にを作成する代わりに、Random引数として渡すか、クラスでメンバー変数を使用する必要があります。

例えば:

static Random rand = new Random();

static public bool TrueOrFalse(int possiblity)
{
      int BallNumber = rand.Next(0, 10); // BallNumber values are from the interval: [0, 10[  (0, 1, 2, ....9)
      // ...

      return true; // if you give it a number higher than 10, it will return true ..
}

MSDNのコメントから:

異なるランダムオブジェクトに同一のシード値を提供すると、各インスタンスは同一の乱数シーケンスを生成します

アプリケーションで異なる乱数シーケンスが必要な場合は、異なるシード値を使用してこのコンストラクターを繰り返し呼び出します。一意のシード値を生成する1つの方法は、それを時間依存にすることです。たとえば、システムクロックからシード値を導出します。ただし、システムクロックには、このコンストラクターのさまざまな呼び出しにさまざまなシード値を提供するのに十分な解像度がない場合があります。これにより、次の例の最初の2つのRandomオブジェクトに示されているように、疑似乱数の同一のシーケンスを生成する乱数ジェネレーターが生成されます。これを防ぐには、アルゴリズムを適用して各呼び出しでシード値を区別するか、Thread.Sleepメソッドを呼び出して、各コンストラクターに異なるシード値を提供するようにします。

于 2012-08-18T22:43:20.687 に答える