真随机不是真正的随机我真的很困惑

时间:2013-03-30 16:19:59

标签: c# random

好吧,我测试了以下方式。

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);
}

以下结果如下:

Between 0-10, missing numbers count: 4, percent: 40%
Between 0-100, missing numbers count: 36, percent: 36%
Between 0-1000, missing numbers count: 369, percent: 36,9%
Between 0-10000, missing numbers count: 3674, percent: 36,74%
Between 0-100000, missing numbers count: 36583, percent: 36,58%
Between 0-1000000, missing numbers count: 367900, percent: 36,79%
Between 0-10000000, missing numbers count: 3678122, percent: 36,78%
Between 0-100000000, missing numbers count: 36797477, percent: 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;
}

3 个答案:

答案 0 :(得分:13)

如评论中所述,您的测试方法已关闭。

您在x和x之间绘制x倍数。特定数字绘制的概率为:

((x-1)/x)^x

当x接近无穷大时,p将朝向1 / e(或大约36.7879441%)这是您在结果中看到的数字。 此外,当x接近无穷大时,您将观察到这个概率作为样本的结果(大数定律)

这与概率有关。当你有一个红色和白色大理石碗。而你拿一个,把它拿回另一个你不能保证你看到两者。你可以把红色的两次。你正在用更多的对象做同样的事情。


详细说明真正的随机性:

  

我预计接近99%而不是64%。或至少90%+百分比。所以你说现在的技术是不可能的

这很简单。由于现代数学,技术和我的超能力,我可以告诉你如何做到这一点:你需要更多的抽奖而不是数字可供选择。公式变为:

more math

其中n是所需的缺失数百分比。例如,如果您愿意接受5%的数字丢失,则必须绘制三倍于随机数的数字。对于1%的几率,您需要迭代最大数量的4.6倍。

此数学假设生成完全均匀的随机数。

答案 1 :(得分:5)

您的结果正是您在更换样品时的均匀分布所期望的结果。

考虑最简单的例子。你有一枚硬币扔两次。因此,我们假设我们从均匀的离散分布中采样。

以0.25的概率发生的可能结果是:

TT
TH
HT
HH

正如您所看到的,四种结果中只有两种具有头部和尾部。

这称为替换采样。所以,一旦我们对尾巴进行采样,然后我们“将它放回袋子里”,它就可以在下一个样品上再次出现。

现在假设我们在没有替换的情况下进行采样在这种情况下,有两种可能的结果:

TH
HT

如您所见,每个可能的值只出现一次。

基本上你对结果的期望是不正确的。作为另一个例子,假设你扔了一枚硬币然后它掉下了尾巴。你期望在下一次投球时会发生什么?你在争论硬币现在必须降下来。但这显然是无稽之谈。


如果您确实想要在没有替换的情况下进行采样,并且不清楚这是否真的是您想要的,那么您可以使用Fisher-Yates shuffle进行采样。

答案 2 :(得分:-1)

如果你想要1亿个独特的随机数,你可以这样做:

现在使用Fisher-Yates的算法:

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;

祝你好运。