随机数生成循环生成相同的数字

时间:2013-10-14 22:45:31

标签: c# for-loop random

我还是C#的新手,我正在尝试建立一个模拟翻转硬币 X 次数的短程序:

        // Declarations
        int headCount = 0;
        int tailCount = 0;

        // Main Program Logic
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)
        {
            Random rnd = new Random();
            int flip = rnd.Next(1, 3);
            if (flip == 1)
            {
                Console.WriteLine("Heads");
                headCount++;
            }
            else
            {
                Console.WriteLine("Tails");
                tailCount++;
            }
        }
        Console.WriteLine("Heads came up {0} times.", headCount);
        Console.WriteLine("Tails came up {0} times.", tailCount);
        if (headCount > tailCount)
        {
            Console.WriteLine("Heads wins.");
        }
        else
        {
            Console.WriteLine("Tails wins.");
        }

        // END OF DOCUMENT
        Console.ReadLine();
    }

现在,我确信我的代码是可靠的,但是,当我运行程序时遇到问题。在上面的代码中,想法是每次执行for循环时都会生成一个新的随机数(1或2)。实际上,在十分之九的情况下,它会在第一次生成一个数字,然后将该数字用于循环执行的其余部分。

每隔一段时间,每个人,结果大约是50/50(你的统计预期),但通常是重复25次的相同结果。

请注意,我在循环中声明了flip变量。我已经在循环中来回移动它,就在循环之前,变化似乎没有任何影响。

我做错了什么或C#喜欢抛弃统计异常?

4 个答案:

答案 0 :(得分:5)

原因是你一直在呼叫new Random()。相反,你应该在循环之外构建它,然后调用.next(int,int)

 Random rnd = new Random();
 for (int x = 1; x <= 25; x++)
 {
        int flip = rnd.Next(1, 3);
        //do stuff
 }

答案 1 :(得分:4)

在循环外部实例化随机数生成器,以便能够正确生成随机数。

原因是种子主要基于cpu时钟。请记住,计算机只能生成“伪随机”数字。为此,他们使用种子和一些数学。如果使用的种子是同一时间(因为循环中的代码以纳秒为单位执行),每个随机数都是相同的。

当在循环之外使用时,种子将为每次调用一个随机数创建一个基础。

答案 2 :(得分:2)

Random rnd = new Random();

这是你的问题。您每次循环都重新初始化生成器。由于您未提供种子,因此默认构造函数使用精确到毫秒的当前时间作为种子。由于循环运行得非常快,因此对于循环的大多数迭代,此数字是相同的,从而导致重复生成相同的数字。

解决方案: 将它移到循环外=)

进一步阅读:Pseudo-Random Number Generators

答案 3 :(得分:0)

您需要在循环之外初始化随机数生成器!

        Random rnd = new Random();
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)

修改 实际上,只需将随机初始化程序移到Console.ReadLine()

之上,我就能从代码中获得良好的分布。

编辑2: 如果您想要 MUCH 更好的随机数,请考虑使用RNGCryptoServiceProvider。

RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
var randomByte = new byte[1];
rnd.GetBytes(randomByte);

当然,使用它并不是很友好(因为它给你随机字节而不是整数)作为随机,但它提供了更好的随机性。然而,这个随机数生成器足以用于密码学,其中Random不应用于密码学。