在C#中快速生成随机数

时间:2012-02-22 20:47:29

标签: c# random

我正在创建一个程序,它创建了几个具有随机确定颜色的面板,这些面板将每20毫秒左右递增/递减一些随机常量,以创建平滑,起伏的颜色。为此,我刚刚使用Random类的Next(int)方法。对于单个实例,这非常有效 - 每次运行程序时,我都会以不同的速率变换不同的颜色。当我尝试创建多个面板时出现问题 - 大多数(如果不是全部)面板的外观和行为相同,这意味着所有随机生成的数字都是相同的。我假设这是快速连续生成所有伪随机数的结果,导致所有伪随机数都基于相同的种子。

有没有比使用Random类快速连续生成随机整数以确保它们不相同的更好的方法?如果C#中没有任何方法,是否有任何直接的方法来开发伪随机数生成器(请记住,这是我第一次尝试使用C#)?

5 个答案:

答案 0 :(得分:5)

不要使用默认构造函数使用Random Class的多个实例。如果它们都在同一时间片内初始化,它们都将具有相同的种子并且将生成相同的随机数序列,使用you can pass in a seed的构造函数并将不同的种子传递给每个实例。

Random rand0, rand1, rand2;

void init()
{
      int baseSeed = (int) DateTime.Now.Ticks;
      rand0 = new Random(baseSeed);
      rand1 = new Random(baseSeed + 1);
      rand2 = new Random(baseSeed + 2);
}

此外,每个线程只需要一个对象,如果它们都在同一个线程上,则对所有面板使用相同的Random对象。

答案 1 :(得分:2)

如果您不需要加密安全的随机数,那么

Random就可以了 - 但是每次需要一个数字时,您可能正在创建一个新实例,而不是使用一个实例整个

当您创建Random的新实例时,它会将“当前时间”作为种子 - 所以如果您快速连续创建两个,那么最终会有两个具有相同种子的实例,因此相同的数字(当你使用相同的电话时)。

通常最好使用Random的单个实例 - 或者更确切地说,每个线程一个实例,因为它不是线程安全的。

有关各种方法,请参阅我的article on the topic

答案 2 :(得分:1)

我更喜欢RNGCryptoServiceProvider。它大致与Random一样快,并且在我的非正式测试中往往会产生更多独特的值。您还可以避免任何与播种有关的不良行为(例如其他人正在描述)。

但是,您无法保证唯一性(否则它不会是随机的)。如果您需要永久跟踪唯一值(它听起来不像您想要的话),可以使用数据库;如果您只关心生成集合,则可以使用随机值为关键字的Dictionary记忆中的唯一数字。如果密钥已存在,则拒绝该值并生成另一个。

using System.Security.Cryptography;

...

RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
byte[] bytes = new byte[8];
crypto.GetBytes( bytes );
long value = BitConverter.ToInt64( bytes, 0 );

答案 3 :(得分:1)

如果您有多个Random类的实例生成相同的随机数系列,那么您必须使用相同的种子创建每个实例。例如:

最可能的解释是你正在创建它们:

var rng = new Random();

并在同一时间点创建每个实例。这个构造函数使用当前时间来为RNG设定种子,如果你在同一个时间点创建它们,那么它们将被同时播种。

通过使用不同的种子创建每个实例来解决问题。或者创建一个RNG并在所有面板之间共享。

答案 4 :(得分:0)

如上所述,您可以使用随机类的单个实例。但是,如果由于某种原因这是不可取的(即您想要运行多个线程并且不想要任何争用),那么只要将每个生成器的种子初始化为a,就可以使用多个实例。随机或伪随机生成的种子。

对于初始种子生成,您需要使用相同的随机生成器。