问题描述:很多时候我们可能需要在极短的时间内生成大量的随机数,但是你可能会发现生成了很多重复的随机数。并不是你所希望生成大量不同的数,或者说相同的数极少。
分析原因:Random是主要产生伪随机数的类,它主要包括两个构造函数(无参构造函数和带一个Int32类型参数的构造函数),无参构造函数主要采用系统时间作为随机种子,带参数的构造函数需要自己去指定随机种子。而在很短的时间内生成大量随机数的时候,由于时间相当短暂,很大的可能性一部分随机数生成时,取到作为随机种子的系统时间相同,因此产生出来的随机数就相同了。
解决方案:既然知道原因何在了,解决方案就可以出来了。要生成不同的随机数,我们只需要保证随机种子尽可能不重复(不能完全保证不重复)即可。Random类有两个构造函数,我们就可以考虑用两种方法去解决这个问题。(有更好、更多的解决办法的朋友,告诉我一声了,呵呵~~)
- 利用无参构造函数,既然它是采用系统时间作为随机种子,而取到的系统时间相同,才造成生成了重复的随机数,因此我们可以在生成一个随机数后延时一段时间,让它下次不取到相同的系统时间,这样随机种子也就不相同了。延时可以考虑使用Thread.Sleep(100),这里是延时0.1秒。
- 利用带参构造函数,我们想办法去生成尽可能不重复的随机种子。注意到MSDN中介绍Random.NextBytes()方法时,有这样一句话“要生成适合于创建随机密码的加密安全随机数,请使用如 RNGCryptoServiceProvider.GetBytes 这样的方法。”,它包含的意义是微软已经有现成的东西生成随机的密码,那我们就可以拿来用用了。我们就用它来生成我们的随机种子。
可以写一个生成随机种子的方法,代码如下:
1 public int GetRandSeed()
2 {
3 byte[] bytes = new byte[8];
4 System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
5 rng.GetBytes(bytes);
6 return BitConverter.ToInt32(bytes, 0);
7 }