人们通常会问为什么使用Random
时他们总是会得到相同的数字。在他们的情况下,他们每次(而不是只使用一个实例),无力地创建一个新的Random
实例,这当然会导致数字始终相同。但就我而言,我确实需要返回不同数字流的Random
的几个实例。
使用硬编码的种子是我认为的一个坏主意,因为您在重新启动程序后一次又一次获得相同的值。这呢:
int seed1 = (int)DateTime.Now.Ticks - 13489565;
int seed2 = (int)DateTime.Now.Ticks - 5564;
我知道这看起来很愚蠢和天真,但是在每个重新启动和两个种子都应该不同之后,它会避免相同的值。也许
Random helper = new Random();
int seed1 = helper.Next(1, int.MaxValue);
int seed2 = helper.Next(1, int.MaxValue);
您可以看到,我在这里有点不创造,需要您的帮助。谢谢。
乔恩·斯基特(Jon Skeet)建议使用辅助Random
对象和锁创建Random
对象工厂。例如:
public static Random NewRandom()
{
lock (globalLock)
{
return new Random(secondaryRandom.Next());
}
}
查看乔恩·斯基特(Jon Skeet)博客中的完整源代码。
我将使用您的第二种方法:
int randomCount = 10;
Random seeder = new Random();
var randoms = Enumerable.Range(0, randomCount)
.Select(i => new Random(seeder.Next()))
.ToList();
这使用LINQ创建了10个不同种子的随机实例的列表。因此,您需要using System.Linq;
才能访问Select
扩展方法。
您还可以将播种机重复使用为您的实例之一:
int randomCount = 10;
Random seeder = new Random();
var randoms = Enumerable.Range(0, randomCount - 1)
.Select(i => new Random(seeder.Next()))
.Concat(new [] { seeder })
.ToList();
您可以使用加密生成器来创建种子,例如
public static Random CreateRandom()
{
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
byte[] bytes = new byte[4];
rng.GetNonZeroBytes(bytes);
int seed = BitConverter.ToInt32(bytes, 0);
return new Random(seed);
}
}
当然,如果您只需要INT,则可以使用RNGCryptoServiceProvider
直接生成它们,尽管System.Random
可能更快。