首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >随机数分布不均匀/不均匀

随机数分布不均匀/不均匀
EN

Stack Overflow用户
提问于 2014-07-27 14:11:49
回答 1查看 506关注 0票数 0

我注意到了c#中随机数生成的一个奇怪问题,看起来集合(模式)比您预期的要频繁得多。

我正在编写一个生成激活代码的机制,该机制由7个数字组成(范围为0-29)。通过计算,应该有30^7 (220亿)可能的激活代码组合。基于此,在生成第10亿个代码之前,不太可能得到一个重复的激活代码。然而,运行我的测试,我开始得到重复的代码后,大约60,000次迭代,这是非常令人惊讶的。我也尝试过使用类似的结果的RNGCryptoServiceProvider,在大约100,000次迭代中得到重复。

我真的很想知道这是.Net中随机数生成的缺陷/限制,还是我做错了什么。

以下代码是验证生成代码的唯一性的测试:

代码语言:javascript
复制
        static void Main(string[] args)
    {
        Random rand = new Random();
        RandomActivationCode(rand, true);
        Console.Out.WriteLine("Press enter");
        Console.ReadLine();
    }

    static void RandomActivationCode(Random randomGenerator)
    {
        var maxItems = 11000000;
        var list = new List<string>(maxItems);
        var activationCodes = new HashSet<string>(list);
        activationCodes.Clear();
        DateTime start = DateTime.Now;
        for (int i = 0; i < maxItems; ++i)
        {
            string activationCode = "";
            for (int j = 0; j < 7; ++j)
            {
                activationCode += randomGenerator.Next(0,30) + "-";
            }
            if (activationCodes.Contains(activationCode))
            {
                Console.Out.WriteLine("Code: " + activationCode);
                Console.Out.WriteLine("Duplicate at iteration: " + i.ToString("##,#"));
                Console.Out.WriteLine("Press enter");
                Console.ReadLine();
                Console.Out.WriteLine();
                Console.Out.WriteLine();
            }
            else
            {
                activationCodes.Add(activationCode);
            }
            if (i % 100000 == 0)
            {

                Console.Out.WriteLine("Iteration: " + i.ToString("##,#"));
                Console.Out.WriteLine("Time elapsed: " + (DateTime.Now - start));
            }

        }
    }

我的解决办法是使用10个数字激活代码,这意味着测试运行时不会产生任何重复的值。这个测试最多需要1100万次迭代(在那之后,它就耗尽了内存)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-27 14:27:09

这一点都不奇怪,这正是你应该期待的。当可能性空间很大时,您认为应该需要很长时间才能生成副本,这是完全错误的,因此不再相信。开始相信真相:如果有n个可能的代码,那么你应该开始在生成的n个代码的平方根上得到重复,如果n是220亿,大约是15万。

这样想一想:当您生成root-n代码时,它们中的大多数已经有了碰撞的机会。把根-n乘以大致的-n-n,然后你得到.大约100%的机会发生碰撞。

这当然不是一个严格的论点,但它应该给你正确的直觉,以取代你错误的信念。如果这个论点不能令人信服,那么你可能想读一下我关于这个主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2010/03/22/socks-birthdays-and-hash-collisions.aspx

如果您想要生成一个唯一的代码,那么就生成一个GUID;这就是它们的用途。注意到GUID不一定是随机的,它只保证是唯一的

另一种产生随机看似代码的方法是生成数字1,2,3,4,.你想要多少都行,然后用乘法逆技术对这些数字进行随机的唯一编码。详情请参见http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24981807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档