如何生成随机整数?

如何在 C#中生成随机整数?

答案

Random用于创建随机数。 (当然是伪随机的。)。

例:

Random rnd = new Random();
int month  = rnd.Next(1, 13);  // creates a number between 1 and 12
int dice   = rnd.Next(1, 7);   // creates a number between 1 and 6
int card   = rnd.Next(52);     // creates a number between 0 and 51

如果要创建多个随机数,则应保留Random实例并重用它。如果创建的新实例在时间上过于接近,则它们将产生与从系统时钟中植入随机生成器相同的一系列随机数。

这个问题看起来很简单,但是答案有点复杂。如果您看到几乎每个人都建议使用 Random 类,而有些人则建议使用 RNG 加密类。但是然后什么时候选择什么。

为此,我们需要首先了解术语 “随机性” 及其背后的原理。

我鼓励您使用 C# https://www.youtube.com/watch?v= tCYxc-2-3fY 观看有关 RANDOMNESS 原理的视频。

首先,我们要了解随机性的原理。当我们告诉某人在红色,绿色和黄色之间进行选择时,内部会发生什么。是什么使人们选择红色,黄色或绿色?

C#随机

一些初步的想法进入决定他选择的人的思想,它可以是喜欢的颜色,幸运的颜色等。换句话说,我们在 RANDOM 中将其称为 SEED 的一些初始触发器。SEED 是起点,促使他选择 RANDOM 值的触发器。

现在,如果易于猜测 SEED,则将这些随机数称为PSEUDO,而当难以猜测种子时,将这些随机数称为SECURED随机数。

例如,一个人选择的颜色取决于天气和声音的组合,那么很难猜测初始种子。

C#随机

现在让我发表重要的声明:

*“Random” 类仅生成 PSEUDO 随机数,而要生成 SECURE 随机数,我们需要使用 “RNGCryptoServiceProvider” 类。

C#随机

随机类从 CPU 时钟中获取种子值,这是非常可预测的。因此,换句话说,C#的 RANDOM 类生成伪随机数,下面是相同的代码。

** 注意:** .NET Core 2.0.0+在无参数构造函数上使用了不同的种子:它使用Guid.NewGuid().GetHashCode()代替 CPU 时钟。

var random = new Random();
int randomnumber = random.Next()

RNGCryptoServiceProvider类使用 OS 熵来生成种子。 OS 熵是一个随机值,它是使用声音,鼠标单击,键盘定时,温度和温度等生成的。下面是相同的代码。

using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider()) 
{ 
    byte[] rno = new byte[5];    
    rg.GetBytes(rno);    
    int randomvalue = BitConverter.ToInt32(rno, 0); 
}

要了解 OS 熵,请观看 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY上的这段视频,其中解释了 OS 熵的逻辑。因此,简单来说,RNG Crypto 会生成 SECURE 随机数。

每次执行 new Random()时,它都会被初始化。这意味着在紧密的循环中,您会多次获得相同的值。您应该保留一个 Random 实例,并在同一实例上继续使用 Next。

//Function to get random number
private static readonly Random getrandom = new Random();

public static int GetRandomNumber(int min, int max)
{
    lock(getrandom) // synchronize
    {
        return getrandom.Next(min, max);
    }
}

请注意, new Random()会在当前时间戳上植入。

如果只想生成一个数字 ,则可以使用:

new Random().Next( int.MinValue, int.MaxValue )

有关更多信息,请查看Random类,但请注意:

但是,由于时钟具有有限的分辨率,因此使用无参数构造函数连续创建不同的 Random 对象会创建随机数生成器,该生成器会生成相同的随机数序列

因此,请勿使用此代码生成一系列随机数。

Random r = new Random();
int n = r.Next();

我想添加一个加密安全的版本:

RNGCryptoServiceProvider 类( MSDNdotnetperls

它实现 IDisposable。

using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
   byte[] randomNumber = new byte[4];//4 for int32
   rng.GetBytes(randomNumber);
   int value = BitConverter.ToInt32(randomNumber, 0);
}

您可以在他为伪随机数构建的 MiscUtil 类库中使用 Jon Skeet 的StaticRandom方法。

using MiscUtil;
...

for (int i = 0; i < 100; 
    Console.WriteLine(StaticRandom.Next());

我尝试了所有这些解决方案,但不包括 COBOL 答案... 大声笑

这些解决方案都不够好。我需要快速进行 int 循环的随机处理,即使在很宽的范围内,我也得到大量重复值。在为某种随机结果解决了太长时间之后,我决定最终一劳永逸地解决这个问题。

都是关于种子的。

我通过解析 Guid 中的非数字来创建随机整数,然后使用该实例化我的 Random 类。

public int GenerateRandom(int min, int max)
{
    var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
    return new Random(seed).Next(min, max);
}

更新 :如果您一次实例化 Random 类,则无需播种。因此,最好创建一个静态类并从中调用一个方法。

public static class IntUtil
{
   private static Random random;

   private static void Init()
   {
      if (random == null) random = new Random();
   }

   public static int Random(int min, int max)
   {
      Init();
      return random.Next(min, max);
   }
}

然后,您可以像这样使用静态类。

for(var i = 0; i < 1000; i++)
{
   int randomNumber = IntUtil.Random(1,100);
   Console.WriteLine(randomNumber); 
}

我承认我更喜欢这种方法。

最好用当前毫秒数为随机对象播种,以确保真正的随机数,并且您几乎不会多次发现重复对象

Random rand = new Random(DateTime.Now.Millisecond);

更新资料

我知道new Random()使用当前的滴答声作为种子,但是以当前毫秒作为种子仍然足够好,因为它是很好的随机开始

最后剩下的一点是,您不必每次需要一个随机数时都初始化new Random() ,可以启动一个 Random 对象,然后在循环中使用它的次数可以满足您的需要。

这里修改答案。

如果您有权访问兼容 Intel Secure Key 的 CPU,则可以使用以下库生成实际的随机数和字符串: https : //github.com/JebteK/RdRandhttps://www.rdrand.com/

只需从此处下载最新版本,包括 Jebtek.RdRand 并为其添加 using 语句即可。然后,您需要做的就是:

// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();

// Generate 10 random characters
string key       = RdRandom.GenerateKey(10);

 // Generate 64 random characters, useful for API keys 
string apiKey    = RdRandom.GenerateAPIKey();

// Generate an array of 10 random bytes
byte[] b         = RdRandom.GenerateBytes(10);

// Generate a random unsigned int
uint i           = RdRandom.GenerateUnsignedInt();

如果没有兼容的 CPU 来执行代码,只需使用 rdrand.com 上的 RESTful 服务即可。使用项目中包含的 RdRandom 包装器库,您只需要这样做(注册时可获得 1000 个免费呼叫):

string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret   = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");