如何在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的哲学.当我们告诉一个人在RED,GREEN和YELLOW之间做出选择时会发生什么.是什么让人选择RED或YELLOW或GREEN?
最初的想法是进入决定他选择的人的心灵,它可以是喜欢的颜色,幸运的颜色等.换句话说,我们将RANDOM中的一些初始触发器称为SEED.此SEED是起始点,触发器促使他选择RANDOM值.
现在,如果SEED易于猜测,那么这些随机数被称为PSEUDO,当种子难以猜测时,这些随机数被称为 SECURED随机数.
例如,一个人根据天气和声音组合选择颜色,那么很难猜测初始种子.
现在让我作一个重要的声明: -
*"Random"类仅生成PSEUDO随机数并生成SECURE随机数,我们需要使用"RNGCryptoServiceProvider"类.
随机类从您的CPU时钟获取种子值,这是非常可预测的.所以换句话说,CAND的RANDOM类生成伪随机数,下面是相同的代码.
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); }
要了解操作系统熵,请参阅此视频,请访问14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY,其中解释了操作系统熵的逻辑.因此,使用简单的单词RNG Crypto会生成SECURE随机数.
每次执行新的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 r = new Random(); int n = r.Next();
我想添加一个加密安全版本:
RNGCryptoServiceProvider类(MSDN或dotnetperls)
它实现了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());
最好用当前的毫秒种子Random对象,以确保真正的随机数,你几乎不会发现多次使用它的重复
Random rand = new Random(DateTime.Now.Millisecond);
更新
我知道new Random()
使用当前的滴答作为种子,但播种当前毫秒仍然足够好,因为它是良好的随机启动
最后一点是你不必new Random()
每次需要一个随机数时初始化,启动一个Random对象然后在循环内或其他任何时候使用它多次
我已经尝试了所有这些解决方案,不包括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); }
我承认我更喜欢这种方法.
从这里修改答案。
如果您有权访问兼容Intel Secure Key的CPU,则可以使用以下库生成实际的随机数和字符串:https : //github.com/JebteK/RdRand和https://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(, " "); uint ret = Randomizer.GenerateUInt(" "); byte[] ret = Randomizer.GenerateBytes( , " ");
内置Random
类(System.Random)生成的数字生成伪随机数.
如果你想要真正的随机数,我们可以得到的最接近的是"安全伪随机生成器",它可以通过使用C#中的加密类生成RNGCryptoServiceProvider
.
即便如此,如果您仍然需要真正的随机数,您将需要使用外部源,例如考虑放射性衰变的设备作为随机数生成器的种子.因为,根据定义,纯粹算法手段产生的任何数字都不能真正随机.
我使用下面的代码来获得一个随机数:
var random = new Random((int)DateTime.Now.Ticks); var randomValue = random.Next(startValue, endValue + 1);
这是我使用的课程。像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); } }