我还是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#喜欢抛弃统计异常?
答案 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();
这是你的问题。您每次循环都重新初始化生成器。由于您未提供种子,因此默认构造函数使用精确到毫秒的当前时间作为种子。由于循环运行得非常快,因此对于循环的大多数迭代,此数字是相同的,从而导致重复生成相同的数字。
解决方案: 将它移到循环外=)
答案 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不应用于密码学。