1

さて、私は以下の方法をテストしました。

生成さxれた時間の間の乱数0~xと、生成されなかったものをチェックします。

100%に限りなく近いと思います。つまり、その間のすべての数値0~xが生成されます。

しかし、結果は衝撃的です。数字の約36%欠落しています。

私のランダム関数は本当にランダムではありませんか?

ここで私のランダムクラスの下に:

private static Random seedGenerator = new Random();

private static ThreadLocal<Random> random = 
    new ThreadLocal<Random>(SeededRandomFactory);

private static Random SeededRandomFactory()
{
    lock (seedGenerator)
        return new Random(seedGenerator.Next());
}

public static int GenerateRandomValueMin(int irRandValRange, int irMinValue)
{
    return random.Value.Next(irMinValue, irMinValue + irRandValRange);
}

ここで、以下の結果:

0 ~ 10 の間、欠落数: 4、パーセント: 40%
0 ~ 100 の間、欠落数: 36、パーセント: 36%
0 ~ 1000 の間、欠落数: 369、パーセント: 36,9%
0 ~ 10000 の間、欠落数: 3674、パーセント: 36,74%
0 ~ 100000 の間、欠落数: 36583、パーセント: 36,58%
0 ~ 1000000 の間、欠落数: 367900、パーセント: 36.79%
0 ~ 10000000 の間、欠落数: 3678122、パーセント: 36,78%
0 ~ 100000000 の間、欠落数: 36797477、パーセント: 36,8%

ここで私がチェックするコード:

File.WriteAllText("results.txt", "");

int irFirst = 10;

for (int i = 0; i < 8; i++)
{
    HashSet<int> hsGenerated = new HashSet<int>();

    for (int k = 0; k < irFirst; k++)
    {
        hsGenerated.Add(GenerateRandomValue.GenerateRandomValueMin(irFirst, 0));
    }

    int irNotFound = 0;
    for (int k = 0; k < irFirst; k++)
    {
        if (hsGenerated.Contains(k) == false)
            irNotFound++;
    }

    string srSonuc = 
        string.Format(
            "Between 0-{0}, missing numbers count: {1}, percent: {2}%", 
            irFirst, irNotFound,
            Math.Round((Convert.ToDouble(irNotFound)/Convert.ToDouble(irFirst))*100.0, 2).ToString()
            );

    using (StreamWriter w = File.AppendText("sonuclar.txt"))
    {
        w.WriteLine(srSonuc);
    }

    irFirst = irFirst * 10;
}
4

3 に答える 3

5

あなたの結果は、置換でサンプリングする一様分布から期待されるものとまったく同じです。

最も単純な例を考えてみましょう。コインを持っていて、それを 2 回投げます。したがって、一様な離散分布からサンプリングしていると仮定します。

0.25 の等確率で発生する可能性のある結果は次のとおりです。

TT
TH
HT
HH

ご覧のとおり、4 つの結果のうち 2 つだけが表と裏の両方を持っています。

これは、置換によるサンプリングとして知られています。したがって、テールをサンプリングしたら、「バッグに戻します」と、次のサンプルで再び出てくる可能性があります。

ここで、置換なしでサンプリングするとします。その場合、次の 2 つの結果が考えられます。

TH
HT

ご覧のとおり、可能な値はそれぞれ 1 回だけ表示されます。

基本的に、結果に対するあなたの期待は正しくありません。別の例として、コインを投げて裏が出たとします。次のトスで何が起こると予想しますか。あなたは、コインが表を出さなければならないと主張しています。しかし、それは明らかにナンセンスです。


置換せずにサンプリングしたいが、それが本当に必要なものであるかが明確でない場合は、Fisher-Yates shuffleを使用して行います。

于 2013-03-30T16:34:39.033 に答える
-1

1 億個の一意の乱数が必要な場合は、次のようにすることができます。

Fisher-Yates suffle アルゴリズムを使用するようになりました。

List<int> numbers = new List<int>(100000000);
for (int i = 0; i < numbers.Capacity; i++)
{
    int rnd = random.Next(numbers.Count + 1);
    if (rnd == numbers.Count)
        numbers.Add(i);
    else
    {
        numbers.Add(numbers[rnd]);
        numbers[rnd] = i;
    }
}

ちなみに、irNotFound はもっと速く計算できます。

int irNotFound = irFirst - hsGenerated.Count;

あなたの探求を頑張ってください。

于 2013-03-30T16:29:11.190 に答える