3

グラフがあります。各ノードには4つの子ノードがあります。開始ノードから終了ノードへのランダムパスを生成するアルゴリズムを作成しました。各ノードで、ランダムな次のノードを選択します。訪問したノードを再訪問できます。

コードは次のようになります。

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;
    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[new Random().Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}

ただし、ランダムが期待どおりに機能しない場合があります。「newRandom()。Next(4)」は0を生成し続けます。したがって、これは常に最初の子ノードが選択され、node1-> node2-> node1-> node2 ...のような非常に長い繰り返しシーケンスが生成され、最終的には生成されます。メモリ不足の例外が発生します。

Randomクラスを正しく機能させる方法はありますか?

4

4 に答える 4

12

その理由は、ランダムが現在の時刻に基づいて初期化されるためです(コンピューターには真のランダムはありません...疑似ランダムのみ)。whileループの反復が速すぎて、システム時刻に変更が登録されていません。したがって、同じ値で始まる新しいRandomオブジェクトを再初期化しています。

メソッド全体で再利用される1つのランダムオブジェクトを作成してみてください。

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;

    Random r = new Random();
    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[r.Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}
于 2012-07-24T00:39:12.947 に答える
5

ループ外のランダムインスタンスを初期化します。例:

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;

    var random = new Random();

    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[random.Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}
于 2012-07-24T00:38:29.077 に答える
0

メソッドが複数のスレッドで呼び出されているとのことですが。解決策は、静的rngによってシードされるスレッドごとに1つの乱数generartorを持つことです。

また、定数4を削除して、に変更しましたnode.Children.Count

static Random seed = new Random();
[ThreadLocal] static Random rng;

public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;

if (rng == null)
   rng = new Random(seed.Next());

while (node != end)
{
    nodes.Add(node);
    var next = node.Children[rng.Next(node.Children.Count)];
    node = next;
}

nodes.Add(end);

return nodes;
}
于 2012-07-24T01:30:15.790 に答える
0

ここであなたに反対することがいくつかあります。1つ目は、要求するたびに異なる数を期待しているということですが、それはこのクラスが行うことでも、ランダムの定義でもありません。したがって、このクラスは実際には正しく機能しています。

ランダムの定義

  1. 方法や意識的な決定なしに行われた、行われた、起こった、または選択された:「100世帯のランダムサンプル」。
  2. 各アイテムによって管理されるか、等しいチャンスが含まれます。

現在、このクラスは、各オプションに選択される機会を均等に与えることに最善を尽くしています。したがって、ランダムについて考えるときは、用語の定義をコンテキストに入れていることを確認してください。ただし、このクラスは人間の心のようには機能しないことを忘れないでください。

さて、あなたが非常に頻繁にゼロになっているという事実に対処するために、それは2つの理由で起こっています。まず、newすべての反復でRandomクラスを作成します。ただし、さらに重要なのは、4つのオプションの範囲で毎回異なる数値が得られることを期待しているため、範囲が小さすぎることです。また、MSDNが同じ回答を頻繁に取得していると述べているように、疑似ランダムであるためです。

4つのオプションしか与えていない理由はわかりますが、フラストレーションが少なくなる可能性があるため、探している機能の種類を再検討する必要があると思います。

于 2012-07-24T01:42:02.277 に答える