1

我还是 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 次相同的结果。

请注意,我在循环内声明了翻转变量。我已经在循环中和循环之前来回移动它,并且更改似乎没有任何效果。

我做错了什么还是 C# 喜欢抛出统计异常?

4

4 回答 4

7

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

 Random rnd = new Random();
 for (int x = 1; x <= 25; x++)
 {
        int flip = rnd.Next(1, 3);
        //do stuff
 }
于 2013-10-14T22:49:05.050 回答
4

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

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

当在循环之外使用时,种子将为每次调用时创建不同的随机数提供基础。

于 2013-10-14T22:52:02.030 回答
2
Random rnd = new Random();

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

解决方案:将其移出循环 =)

进一步阅读:伪随机数生成器

于 2013-10-14T22:50:36.630 回答
0

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

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

编辑: 实际上,我只需将随机初始化程序向上移动到 Console.ReadLine() 上方,就可以从您的代码中获得良好的分布

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

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

当然,它不像 Random 那样易于使用(因为它给你的是随机字节而不是整数),但它提供了更好的随机性。然而,这个随机数生成器足以用于密码学,而 Random 不应该用于密码学。

于 2013-10-14T22:47:21.013 回答