人们通常会问为什么在使用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);
正如你所看到的,我在这里有点无创,需要你的帮助。感谢。
答案 0 :(得分:4)
我会用你的第二种方法:
int randomCount = 10;
Random seeder = new Random();
var randoms = Enumerable.Range(0, randomCount)
.Select(i => new Random(seeder.Next()))
.ToList();
这使用linq创建10个不同种子的Random实例的列表。因此,您需要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();
答案 1 :(得分:4)
Jon Skeet建议使用辅助Random
对象和锁来创建Random
对象工厂。例如:
public static Random NewRandom()
{
lock (globalLock)
{
return new Random(secondaryRandom.Next());
}
}
Take a look at the complete source code in Jon Skeet's blog.
答案 2 :(得分:1)
您可以使用加密生成器来创建种子,例如
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);
}
}
当然,如果您只需要整数,那么您可以使用RNGCryptoServiceProvider
直接生成它们,但System.Random
可能更快。