提问



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

最佳参考


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


例:


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实例并重复使用它。如果您创建新实例的时间太近,它们将生成相同系列的随机数,因为随机生成器是从系统时钟播种的。

其它参考1


每次执行新的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);
    }
}

其它参考2


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


为此,我们首先需要理解随机性一词及其背后的哲学。


我鼓励你观看这段视频,该视频深入探讨了使用C#https://www.youtube.com/watch?v=tCYxc-2-3fY [45]的RANDOMNESS哲学


首先让我们了解RANDOMNESS的哲学。当我们告诉一个人在RED,GREEN和YELLOW之间做出选择时会发生什么。是什么让一个人选择RED或YELLOW或GREEN?


[46]


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


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


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


[47]


现在让我作一个重要的声明: -


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


[48]


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


Random rnd= new Random();
int rndnumber = rnd.Next()


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


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


要了解操作系统熵,请参阅此视频https://www.youtube.com/watch?v=tCYxc-2-3fY 11:20,其中解释了OS熵的逻辑。因此,使用简单的单词RNG Crypto会生成安全随机数。[49]

其它参考3


注意new Random()是在当前时间戳上播种的。


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


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


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



  但是,由于时钟具有有限的分辨率,使用无参数构造函数以紧密连续的方式创建不同的随机对象会创建随机数生成器,从而生成相同的随机数序列



所以不要使用此代码生成一系列随机数。

其它参考4


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

其它参考5


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


RNGCryptoServiceProvider类(MSDN或dotnetperls)[51] [52]


它实现了IDisposable。


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

其它参考6


最好用当前的毫秒来播种Random对象,以确保真正的随机数,你几乎不会发现重复使用它多次


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

其它参考7


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


using System;
using MiscUtil;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine(StaticRandom.Next());
        }
    }
}

其它参考8


我已经尝试了所有这些解决方案,不包括COBOL答案......哈哈


这些解决方案都不够好。我需要在快速的int循环中使用random,即使在很宽的范围内,我也会获得大量的重复值。在解决了一段随机结果后,我决定一劳永逸地解决这个问题。


这完全取决于种子。


我通过解析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); 
}


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

其它参考9


由内置Random类(System.Random)生成的数字生成伪随机数。


如果你想要真正的随机数,我们可以得到的最接近的是安全伪随机生成器,它可以通过使用C#中的加密类生成,如RNGCryptoServiceProvider


即便如此,如果您仍需要 true 随机数,您将需要使用外部源,例如考虑放射性衰变的设备作为随机数生成器的种子。因为,根据定义,纯粹算法手段生成的任何数字都不能真正随机。

其它参考10


我使用下面的代码来获得一个随机数:


var random = new Random((int)DateTime.Now.Ticks);
var randomValue = random.Next(startValue, endValue + 1);

其它参考11


Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);

其它参考12


修改后的答案。


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


只需从这里下载最新版本,包括Jebtek.RdRand并为其添加一个using语句。那么,你需要做的就是:[57]


bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters
string apiKey = RdRandom.GenerateAPIKey(); //Generate 64 random characters, useful for API keys
byte[] b = RdRandom.GenerateBytes(10); //Generate an array of 10 random bytes
uint i = RdRandom.GenerateUnsignedInt() //Generate a random unsigned int


如果您没有兼容的CPU来执行代码,只需使用rdrand.com上的RESTful服务。使用项目中包含的RdRandom包装程序库,您只需要执行此操作(当您执行此操作时,您将获得1000个免费调用注册):


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

其它参考13


虽然这没关系:


Random random = new Random();
int randomNumber = random.Next()


您希望在大多数时间控制限制(最小和最大数量)。因此您需要指定随机数的开始和结束位置。


Next()方法接受两个参数,min和max。


因此,如果我希望我的随机数在5到15之间,我就是这么做的


int randomNumber = random.Next(5, 16)

其它参考14


这是我使用的课程。像RandomNumber.GenerateRandom(1, 666)这样的作品


internal static class RandomNumber
{
    private static Random r = new Random();
    private static object l = new object();
    private static Random globalRandom = new Random();
    [ThreadStatic]
    private static Random localRandom;
    public static int GenerateNewRandom(int min, int max)
    {
        return new Random().Next(min, max);
    }
    public static int GenerateLockedRandom(int min, int max)
    {
        int result;
        lock (RandomNumber.l)
        {
            result = RandomNumber.r.Next(min, max);
        }
        return result;
    }
    public static int GenerateRandom(int min, int max)
    {
        Random random = RandomNumber.localRandom;
        if (random == null)
        {
            int seed;
            lock (RandomNumber.globalRandom)
            {
                seed = RandomNumber.globalRandom.Next();
            }
            random = (RandomNumber.localRandom = new Random(seed));
        }
        return random.Next(min, max);
    }
}

其它参考15


Random rand = new Random();
int name = rand.Next()


在第二个括号中放置您想要的任何值
确保通过编写prop和double选项卡来设置名称以生成代码

其它参考16


计算机通过确定性过程计算的数字,根据定义,不能是随机的。


如果你想要一个真正的随机数,随机性来自大气噪声或放射性衰变。


您可以尝试例如RANDOM.ORG(它会降低性能)

其它参考17


我想证明每次使用新的随机生成器时会发生什么。假设您有两个方法或两个类,每个类都需要一个随机数。你天真地对它们进行编码,如:


public class A
{
    public A()
    {
        var rnd=new Random();
        ID=rnd.Next();
    }
    public int ID { get; private set; }
}
public class B
{
    public B()
    {
        var rnd=new Random();
        ID=rnd.Next();
    }
    public int ID { get; private set; }
}


你认为你会得到两个不同的身份证吗?的 NOPE


class Program
{
    static void Main(string[] args)
    {
        A a=new A();
        B b=new B();

        int ida=a.ID, idb=b.ID;
        // ida = 1452879101
        // idb = 1452879101
    }
}


解决方案是始终使用单个静态随机生成器。喜欢这个:


public static class Utils
{
    public static readonly Random random=new Random();
}

public class A
{
    public A()
    {
        ID=Utils.random.Next();
    }
    public int ID { get; private set; }
}
public class B
{
    public B()
    {
        ID=Utils.random.Next();
    }
    public int ID { get; private set; }
}

其它参考18


为什么不用int randomNumber = Random.Range(start_range, end_range)?

其它参考19


尝试这些简单的步骤来创建随机数:


创建功能


private int randomnumber(int min, int max)
{
    Random rnum = new Random();
    return rnum.Next(min, max);
}


在要使用随机数的位置使用上述功能。假设您要在文本框中使用它。


textBox1.Text = randomnumber(0, 999).ToString();


0表示最小值,999表示最大值。您可以将值更改为您想要的任何值。


另请查看此页面上的答案。[58]


(http://solutions.musanitech.com/c-how-to-create-random-numbers/)[59]

其它参考20


您可以使用下面的随机种子值尝试:


var rnd = new Random(11111111); //note: seed value is 11111111

string randomDigits = rnd.Next().ToString().Substring(0, 8);

var requestNumber = $"SD-{randomDigits}";

其它参考21


内联快速简便,使用以下代码:


new Random().Next(min, max);

// for example unique name
strName += "_" + new Random().Next(100, 999);

其它参考22


我总是有方法生成随机数,这有助于各种目的。我希望这对你也有帮助:


public class RandomGenerator  
{  
    public int RandomNumber(int min, int max)  
    {  
        Random random = new Random();  
        return random.Next(min, max);  
    }  

    public string RandomString(int size, bool lowerCase)  
    {  
        StringBuilder builder = new StringBuilder();  
        Random random = new Random();  
        char ch;  
        for (int i = 0; i < size; i++)  
        {  
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));  
            builder.Append(ch);  
        }  
        if (lowerCase)  
            return builder.ToString().ToLower();  
        return builder.ToString();  
    }  
}

其它参考23


对于强随机种子,我总是使用CryptoRNG而不是Time。


using System;
using System.Security.Cryptography;

public class Program
{
    public static void Main()
    {
        var random = new Random(GetSeed());
        Console.WriteLine(random.Next());
    }

    public static int GetSeed() 
    {
        using (var rng = new RNGCryptoServiceProvider())
        {
            var intBytes = new byte[4];
            rng.GetBytes(intBytes);
            return BitConverter.ToInt32(intBytes, 0);
        }
    }
}

其它参考24


重复使用一个Random实例


// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
    Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
    // Assume there'd be more logic here really
    return rng.Next(10);
}


本文将介绍为什么随机性会导致如此多的问题,以及如何解决这些问题。
http://csharpindepth.com/Articles/Chapter12/Random.aspx[60]

其它参考25


我假设您需要一个均匀分布的随机数生成器,如下所示。包括C#和C ++在内的大多数编程语言中的随机数在使用之前没有被正确地改组。这意味着你会反复得到相同的数字,这不是非常随机的。为了避免一遍又一遍地绘制相同的数字,你需要一个种子。通常,时间的滴答对于这个任务是可以的。记住你如果你每次都使用相同的种子会反复得到相同的数字。所以尽量使用不同的种子。时间是种子的良好来源,因为它们总是变化。


int GetRandomNumber(int min, int max)
{
    Random rand = new Random((int)DateTime.Now.Ticks);
    return rand.Next(min, max);
}


如果您正在寻找正态分布的随机数生成器,您可以使用Box-Muller转换。通过yoyoyoyosef在随机高斯变量问题中检查答案。由于您需要整数,因此必须在结尾处将double值转换为整数。


Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
         Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
         mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)


随机高斯变量

其它参考26


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


您还可以为Next()函数赋予最小值和最大值。喜欢


 int n = new Random().Next(5,10);