如何播种随机类以避免获得重复的随机值

leo*_*ora 110 c# random

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

Random r = new Random();
int randomNumber = r.Next(1,100);
Run Code Online (Sandbox Code Playgroud)

我在循环中有这个,我一直都这样randomNumber!

这里有什么建议?

jop*_*aus 305

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

Random rand = new Random(Guid.NewGuid().GetHashCode());
Run Code Online (Sandbox Code Playgroud)

这是非常随机的.种子总是不同的,因为种子也是随机产生的.

  • +1优雅的随机发电机!谢谢,这就是我在Google上搜索的内容. (21认同)
  • `Guid.NewGuid()`实际上必须使用随机生成器来创建GUID(以及其他数据,如时间和位置).它也比使用没有参数的`new Random()`慢,后者从系统时间设置种子,并且不是随机的. (13认同)
  • 从技术上讲,基于Guid的种子不是随机的,但具有一定程度的独特性.此外,使用GetHashCode()可以减少唯一性,因为Guid可以获取比int更多的值.对于许多(如果不是大多数)情况来说,这已经足够了. (11认同)
  • 解决了我的问题,两个应用程序在同一时间启动并获得完全相同的种子值. (5认同)
  • @AndréChristofferAndersen你怎么知道的?http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/00000/2000/300/2318/2318.strip.gif (3认同)
  • @ChrisNash系统时间在循环的context_中不是随机的.为什么?因为它改变_overtime_,而cumputers一般都该死!OP获得相同序列的原因是_beause_默认构造函数种子随时间变化,计算机速度太快,以系统精度测量的时间在循环中不会发生明显变化.因此,使用时间紧密连续播种多个发电机是一个常见的错误. (3认同)
  • @AnorZaken,但使用不同(较慢)的方法来播种多个随机数生成器实例是一个糟糕的解决方案。好的解决方案是重用随机数生成器的单个实例。 (2认同)

Meh*_*ari 99

您不应该Random在循环中创建新实例.尝试类似的东西:

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

由单个Random实例生成的随机数序列应该是均匀分布的.通过Random快速连续为每个随机数创建一个新实例,您可能会使用相同的值为它们播种,并使它们生成相同的随机数.当然,在这种情况下,生成的序列将远离均匀分布.

为了完整起见,如果你真的需要重新设置a Random,你将Random使用新种子创建一个新实例:

rnd = new Random(newSeed);
Run Code Online (Sandbox Code Playgroud)

  • @harigm:通常,(伪)随机数生成器是给定初始数(称为*种子*)的确定性算法,生成一系列充分满足统计随机性测试的数字.由于算法是确定性的,如果用同一种子初始化算法,算法将始终生成完全相同的数字序列.这就是为什么系统时间(一直在变化的东西)通常被用作随机数生成器的种子. (17认同)

Orp*_*hid 19

稍晚,但System.Random使用的实现Environment.TickCount:

public Random() 
  : this(Environment.TickCount) {
}
Run Code Online (Sandbox Code Playgroud)

这避免了必须DateTime.UtcNow.Ticks从长时间投射,这无论如何都是有风险的,因为它不表示自系统启动以来的刻度,而是"自从0001年1月1日午夜12:00:00起经过的100纳秒间隔的数量(0 :00:00 UTC,1月1日,在公历中,"格里高利历

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

  • @hashtable 这通常是个好主意,但并非所有测试都是单元测试。在系统/集成测试中,引入不太可预测的行为可以增加测试面 - 如果您没有资源在单个测试运行中检查每个可能的输入,则很有用。 (2认同)

PPC*_*PPC 16

如果由于某种原因你不能Random一次又一次地使用它,尝试用一直在变化的东西来初始化它,比如时间本身.

new Random(new System.DateTime().Millisecond).Next();
Run Code Online (Sandbox Code Playgroud)

记住这是不好的做法.

编辑:默认构造函数已经从时钟中获取其种子,并且可能比我们更好.引自MSDN:

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

下面的代码可能是您的最佳选择:

new Random().Next();
Run Code Online (Sandbox Code Playgroud)

  • 你会得到一个(小)更好的随机性,用一个更大的不太可预测的数字播种随机数,比如新的Random((int)DateTime.Now.Ticks) (4认同)
  • 无论如何,我认为默认种子是系统启动时间以来的刻度. (3认同)
  • 如果Random类在相同的毫秒内被多次初始化(就像在快速循环中一样),这根本没有帮助.`DateTime.Now.Ticks`也没有足够快地更新. (3认同)

McK*_*Kay 5

public static Random rand = new Random(); // this happens once, and will be great at preventing duplicates
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,与 Java 不同,.NET 中的“Random”不是线程安全的。在不同线程上没有适当锁定机制的情况下调用 Next 可能会导致随机数生成器的内部状态损坏。 (7认同)
  • @Jason:在大多数情况下,获得异常比处理糟糕的结果要好。我宁愿让我的在线扑克应用程序崩溃而不是易于预测 (3认同)
  • @Mehrdad:或者更糟;我已经让它抛出异常。 (2认同)
  • @PPC 在那种情况下你应该选择 [crypto random](http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator(v=vs.110).aspx) (2认同)