为什么不随机()随机?
可能重复:
Why does this Random Number Generator not random?为什么不随机()随机?
我有这个测试程序:
static void Main(string[] args)
{
var randomNumbers = new Dictionary<int, int>();
foreach (var s in Enumerable.Range(1, 500))
{
var rand = Rand5();
if (!randomNumbers.ContainsKey(rand))
randomNumbers.Add(rand, 1);
else
randomNumbers[rand] += 1;
}
randomNumbers
.ToList()
.ForEach(x => Console.WriteLine("{0}: {1}", x.Key, x.Value));
Console.ReadLine();
}
static int Rand5()
{
System.Threading.Thread.Sleep(1);
return new Random().Next(1, 6);
}
如果我注释掉System.Threading.Thread.Sleep(1);
,我得到
5: 500
但是,如果我取消注释该行,我会得到随机数。
2: 87
4: 94
1: 116
5: 108
3: 95
为什么代码行很重要?谢谢!
正如其他人所说,new Random()
种子从当前系统时间的随机数发生器。
我有an article更详细地描述了这一点,包括对问题的解决方案,您可能会发现有用。基本上你想多次使用同一个Random
的实例 - 但是观察它是而不是线程安全。
感谢您的答案和详细的解释。顺便说一下,我正在阅读你的C#深度2 :) – bla 2011-01-27 15:38:44
因为它使用的时钟作为种子生成的数字,当你以这种方式产生的随机数,你会得到
随机数生成部分基于系统时钟相同的数字,和C#太快速搅动它们...
Random
类型默认根据当前系统时间,具有有限的粒度种子。
快速连续多次调用new Random().Next(1, 6)
将因此构造多个具有相同种子值的对象,产生相同的结果。 Thread.Sleep(1)
通过简单地将构建体间隔得更远,从而“解决”了这个问题,增加了不同种子值的概率。
你需要从一个呼叫保留特定Random
对象到下一个:
var randomNumbers = new Dictionary<int, int>();
var random = new Random(); // Re-use this, don't keep creating new ones.
foreach (var s in Enumerable.Range(1, 500))
{
var rand = random.Next(1, 6);
// ...
如果不播种随机的,你会得到相同数量的随机是一个伪随机发生器
使用的Thread.Sleep(1)您允许计时器提前并产生一个新的自动生成的种子。
“修复”的一种方法是创建1个随机对象并重用它(就像其他一些人也回答的那样),或者使用不同的随机生成器。在http://msdn.microsoft.com/en-us/library/ctssatww.aspx
你使用任何随机数发生器
更多信息是一个伪随机数。这将始终具有预定义的种子值,适用于测试,但不适用于实现真随机性的特征。
您应该使用一个准随机数字序列来生成随机数字或更好,马尔可夫链来生成最好的随机数字。如果你打算使用这些随机函数中的一个,你将不会有任何接近真正的随机性的东西。
我认为将这些问题标记为愚蠢是徒劳无益的,因为大概三分之一*随机*标记的问题都是相同的问题。 – Joey 2011-01-27 16:49:40