Random not that random
我用随机数生成一个随机数序列。我只是构造一次随机对象,然后在循环中生成随机值(其中300个)。问题是,一旦我得到所有的值并对它们进行排序,我就会意识到其中一些值是相等的和/或是连续的:我生成的数字是从0到50000。
这是我的剧本:
1 2 3 4 5 6 | Random rnd = new Random(); for (int n=0; n < 300; n++) { int RndNumber = rnd.Next(0, 50000); System.Threading.Thread.Sleep(3); } |
有人能知道为什么会发生这种情况吗?我该如何改进这种情况,使之更加随机?
这就是生日悖论*。从50000中抽取300个数字时,其中至少两个数字相等的近似概率为
1 2 | p(300) = 1 - exp(-300 * 300 / (2 * 50000)) = 0.59 |
(我可以算出确切的概率,但我很懒!)
所以,发生碰撞的可能性更大。顺序更可能(现在不需要碰撞,只需要
随机是易变的。
*如果你不熟悉它,它说如果一个房间里有23个人,那么至少有两个人共享同一个生日的可能性更大。
!好吧,我算出来了。是0.59538305549951746819986449….
研究:
嗨,伙计们,
如果使用不带参数
Random():"Initializes a new instance of the Random class, using a time-dependent"
http://msdn.microsoft.com/en-us/library/system.random.aspx
所以,如果我这样尝试:
1 2 3 4 5 |
在一千次通话中,我只收到三个不同的号码,大约300次!不是那么随机…
在构造函数
例如,
对于"实数"随机数,我们需要的是一个不断变化的种子,它与时间无关。
我正在使用更改值的哈希代码:
例如:
结果:
1 2 3 4 5 | Random ran = new Random(Guid.NewGuid().GetHashCode()); for(int i = 0; i < 1000; i++) { Console.WriteLine(ran.Next(50001)); } |
或(为了获得更好的性能):
1 2 3 4 5 6 | for(int i = 0; i < 1000; i++) { int val = Guid.NewGuid().GetHashCode() % 50001; val = val > 0 ? val : -val; Console.WriteLine(val); } |
ps:下一个(max)方法的最大值总是max-1;
->run.next(11)可以返回0、1、2、…、8、9、10。不是11!
问候Bahamut=)
作为解释为什么你会偶尔看到重复,杰森的回答是对的。
如果你想要的是300个不同的随机数,那么这样的数字怎么样?
1 2 3 4 5 6 7 8 9 10 | 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); |