我使用Random来生成随机数序列。我只构造一次随机对象,然后在循环内生成随机值(其中300个)。问题是,一旦我获得所有值并对它们进行排序,我就会发现其中一些是相同的和/或顺序的:我生成的数字从0到50000。
这是我的剧本:
Random rnd = new Random();
for (int n=0; n < 300; n++)
{
int RndNumber = rnd.Next(0, 50000);
System.Threading.Thread.Sleep(3);
}
有人能够知道为什么会发生这种情况,我该如何改进这一点以使其更随机?
答案 0 :(得分:21)
所以这就是生日悖论 * 。当您从50000中抽取300个数字时,其中至少两个相等的概率是
p(300) = 1 - exp(-300 * 300 / (2 * 50000))
= 0.59
(我可以算出确切的概率,但我懒得!。)
所以,你很可能会发生碰撞。顺序更有可能(现在你不需要碰撞,你只需要n - 1
和n
或n
和n + 1
来点击某些{{1} })。
随机是善变的。
* :如果你不熟悉它,它会说如果你在一个房间里有二十三个人,那么房间里至少有两个人就更有可能分享同一个生日。
!:好的,我把它解决了。这是0.5953830515549951746819986449 ....
答案 1 :(得分:12)
<强>研究强>
大家好,
如果使用不带参数new Random()
的构造函数,则种子取决于当前的servertime。
Random():“使用时间依赖性初始化Random类的新实例” http://msdn.microsoft.com/en-us/library/system.random.aspx
所以,如果我这样试试:
for(int i = 0; i < 1000; i++)
{
Random ran = new Random();
Console.WriteLine(ran.Next(50001));
}
我在一千个电话中只得到3个不同的数字约300次!不是那么随意......
在构造函数new Random(0)
中设置种子会返回一组数字修复。
e.g。 new Random(0).Next(50)
永远!返回36.如果您不信任我,请自行尝试;
我们对“真实”随机数的需求是变化的种子,这与时间无关。
我正在使用更改值的Hashcode:
e.g。 Guid.NewGuid().GetHashCode()
或DateTime.Now.GetHashCode()
<强>结果:强>
Random ran = new Random(Guid.NewGuid().GetHashCode());
for(int i = 0; i < 1000; i++)
{
Console.WriteLine(ran.Next(50001));
}
或(为了更好的表现):
for(int i = 0; i < 1000; i++)
{
int val = Guid.NewGuid().GetHashCode() % 50001;
val = val > 0 ? val : -val;
Console.WriteLine(val);
}
PS:Next(max)方法的最大值总是max - 1;
- &GT; ran.Next(11)可以返回0,1,2,...,8,9,10。不是11!
Greets Bahamut =)
答案 2 :(得分:11)
作为对为什么的解释,您偶尔会看到重复,Jason's answer就是正确的。
如果您想要的是300个不同的随机数,那么这样的事情呢?
static IEnumerable<int> GetRandoms(int min, int max)
{
var rand = new Random();
while (true)
{
yield return rand.Next(min, max);
}
}
var distinctRandoms = GetRandoms(0, 50000).Distinct().Take(300);