我如何种子一个随机类,以避免得到重复的随机值

我在静态类的静态方法中有以下代码:

Random r = new Random();
int randomNumber = r.Next(1,100);

我在一个循环中得到了这个,并且我得到了相同的 randomNumber

有什么建议吗?

216276 次浏览

不应该在循环中创建新的 Random实例:

var rnd = new Random();
for(int i = 0; i < 100; ++i)
Console.WriteLine(rnd.Next(1, 100));

一个 Random实例生成的随机数序列应该是均匀分布的。通过为每个快速连续的随机数创建一个新的 Random实例,您可能会为它们输入相同的值,并让它们生成相同的随机数。当然,在这种情况下,生成的序列远非均匀分布。

为了完整起见,如果您确实需要重新播种 Random,您将使用新的种子创建一个新的 Random实例:

rnd = new Random(newSeed);
public static Random rand = new Random(); // this happens once, and will be great at preventing duplicates

注意,这不是用于加密目的。

如果由于某种原因不能一次又一次地使用相同的 Random,那么可以尝试使用一些一直在变化的东西来初始化它,比如时间本身。

new Random(new System.DateTime().Millisecond).Next();

记住,这是不好的练习。

编辑: 缺省构造函数已经从时钟中获得了它的种子,而且可能比我们更好:

Random () : 使用与时间相关的默认种子值初始化 Random 类的新实例。

下面的代码可能是你最好的选择:

new Random().Next();

这对我有用:

private int GetaRandom()
{
Thread.Sleep(1);
return new Random(DateTime.Now.Millisecond).Next();
}

一个好的种子初始化可以像这样完成

Random rnd = new Random((int)DateTime.Now.Ticks);

刻度将是唯一的,并且转换成一个可能有松散值的整型将是可以的。

对我来说,一个好的种子世代是:

Random rand = new Random(Guid.NewGuid().GetHashCode());

它是非常随机的。种子总是不同的,因为种子也是随机生成的。

我在大多数情况下使用这个,如果需要重复这个序列,就保留这个种子

    var seed = (int) DateTime.Now.Ticks;
var random = new Random(seed);

或者

    var random = new Random((int)DateTime.Now.Ticks);

有点晚,但系统使用的是 实施。随机是 Environment.TickCount:

public Random()
: this(Environment.TickCount) {
}

这样就避免了从一个长的数据库中转换 DateTime.UtcNow.Ticks,这样做是有风险的,因为它并不代表系统启动后的刻度,而是“从1月1日午夜12:00:00到1月1日100纳秒间隔的数量(1月1日世界协调时0:00:00,在公历中)”。

正在为 TestApi 的 StringFactory.GenerateRandomString寻找一个好的整数种子