How do I generate a random int number?
如何在C中生成随机整数?
例子:
1 2 3 4 | 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()时,它都会被初始化。这意味着在一个紧密的循环中,你会多次得到相同的值。您应该保留一个随机实例,并在同一个实例上继续使用next。
1 2 3 4 5 6 7 8 9 10 | //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); } } |
这个问题看起来很简单,但答案有点复杂。如果你看到几乎每个人都建议使用随机类,有些人建议使用RNG加密类。但是什么时候选择什么。
为此,我们需要首先理解"随机性"这个术语及其背后的哲学。
我鼓励你观看这段视频,它深入了解随机性的原理,使用c https://www.youtube.com/watch?V= TCYXC-2-3FY
首先让我们理解随机性的哲学。当我们告诉一个人在红色、绿色和黄色之间做出选择时,内部会发生什么。是什么让一个人选择红色、黄色或绿色?
一些最初的想法进入了决定他选择的人的头脑,它可以是最喜欢的颜色,幸运的颜色等等。换句话说,我们随机称之为种子的初始触发器。这个种子是开始点,是促使他选择随机值的触发器。
如果一个种子很容易猜测,那么这些随机数就称为伪随机数,当一个种子很难猜测时,这些随机数就称为安全随机数。
例如,一个人选择的颜色取决于天气和声音的组合,那么很难猜测最初的种子。
现在让我做一个重要的声明:
*"random"类只生成伪随机数,要生成安全随机数,我们需要使用"rngcryptoServiceProvider"类。
随机类从CPU时钟获取种子值,这是非常可预测的。所以换句话说,C的随机类生成伪随机数,下面是相同的代码。
1 2 |
而rngCryptoServiceProvider类使用操作系统熵来生成种子。操作系统熵是一个随机值,它是由声音、鼠标点击和键盘计时、热温度等产生的。下面的代码是相同的。
1 2 3 4 5 6 |
要了解操作系统熵,请看14:30的视频https://www.youtube.com/watch?v=tcyxc-2-3fy,其中解释了操作系统熵的逻辑。因此,输入简单的单词rng crypto会生成安全的随机数。
注意,
如果只想生成一个数字,可以使用:
有关更多信息,请查看随机类,不过请注意:
However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers
因此,不要使用此代码生成一系列随机数。
1 2 |
我想添加一个加密安全版本:
RNGCryptoServiceProvider类(msdn或dotnetperls)
它实现IDisposable。
1 2 3 4 5 6 |
你可以在他为伪随机数构建的miscutil类库中使用jon skeet的staticrandom方法。
1 2 3 4 5 | using MiscUtil; ... for (int i = 0; i < 100; Console.WriteLine(StaticRandom.Next()); |
最好以当前毫秒为随机对象种子,以确保真正的随机数,并且使用它多次几乎找不到重复项。
1 |
更新
我知道
最后一点是,您不必每次需要一个随机数时都初始化
我尝试过所有这些解决方案,除了COBOL的答案…大声笑
这些解决方案都不够好。我需要一个快速的randoms for int循环,即使在非常宽的范围内,我也得到了大量的重复值。在解决了太长时间的随机结果之后,我最终决定一次性解决这个问题。
一切都是为了种子。
我通过解析guid中的非数字来创建一个随机整数,然后用它来实例化我的随机类。
1 2 3 4 5 | 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); } |
更新:如果将随机类实例化一次,则不需要进行种子设定。所以最好创建一个静态类并调用一个方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); } } |
然后您可以像这样使用静态类。
1 2 3 4 5 | for(var i = 0; i < 1000; i++) { int randomNumber = IntUtil.Random(1,100); Console.WriteLine(randomNumber); } |
我承认我更喜欢这种方法。
由内置
如果您想要真正的随机数,我们能得到的最接近的是"安全伪随机生成器",它可以通过使用C中的加密类(如
即使如此,如果你仍然需要真正的随机数,你将需要使用一个外部的来源,如计算放射性衰变的设备作为随机数生成器的种子。因为,根据定义,任何由纯算法方法生成的数字都不能是真正随机的。
我用下面的代码有一个随机数:
1 2 | var random = new Random((int)DateTime.Now.Ticks); var randomValue = random.Next(startValue, endValue + 1); |
从这里修改了答案。
如果您可以访问与Intel Secure Key兼容的CPU,则可以使用以下库生成真正的随机数和字符串:https://github.com/jebtek/rdrand和https://www.rdrand.com/
从这里下载最新版本,包括jebtek.rdrand并为其添加一个using语句。那么,你需要做的就是:
1 2 3 4 5 | 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个免费调用):
1 2 3 | string ret = Randomizer.GenerateKey(<length>,"<key>"); uint ret = Randomizer.GenerateUInt("<key>"); byte[] ret = Randomizer.GenerateBytes(<length>,"<key>"); |
这是我使用的课程。像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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); } } |
1 2 |
当一切正常时:
1 2 |
大多数情况下你都想控制极限(最小和最大)。所以您需要指定随机数的起始和结束位置。
所以如果我想让我的随机数在5到15之间,我就这么做
1 | int randomNumber = random.Next(5, 16) |
我想演示一下每次使用新的随机生成器时会发生什么。假设您有两个方法或两个类,每个方法或类都需要一个随机数。你天真地把它们编码成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
你认为你会得到两个不同的身份证吗?不
1 2 3 4 5 6 7 8 9 10 11 12 |
解决方案是始终使用单个静态随机生成器。这样地:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; } } |
计算机通过确定性过程计算出的数字,根据定义,不能是随机的。
如果你想要一个真正的随机数,随机性来自大气噪音或放射性衰变。
您可以尝试例如random.org(它会降低性能)
1 2 |
在第二个圆括号中放入您想要的任何值确保通过编写prop和double tab来设置名称以生成代码
对于强随机种子,我总是使用密码学而不是时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } } } |
您可以尝试使用以下随机种子值:
1 2 3 4 5 | var rnd = new Random(11111111); //note: seed value is 11111111 string randomDigits = rnd.Next(); var requestNumber = $"SD-{randomDigits}"; |
我假设您需要一个如下的均匀分布随机数生成器。包括C语言和C++的大多数编程语言中的随机数在使用它们之前都没有被正确地洗牌。这意味着你将得到相同的数字,一次又一次,这不是真正随机的。为了避免一次又一次地绘制相同的数字,您需要一个种子。通常,此任务的时间刻度是可以的。记住,如果每次使用相同的种子,您将得到相同的数字。所以试着用不同的种子。时间是种子的好来源,因为它们总是痛苦的。
1 2 3 4 5 | int GetRandomNumber(int min, int max) { Random rand = new Random((int)DateTime.Now.Ticks); return rand.Next(min, max); } |
如果您正在寻找用于正态分布的随机数生成器,则可以使用Box-Muller转换。用Yoyoyoyosef检查随机高斯变量问题的答案。由于您需要整数,所以必须在末尾将双精度值强制转换为整数。
1 2 3 4 5 6 7 | 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) |
随机高斯变量
尝试以下简单步骤创建随机数:
创建函数:
1 2 3 4 5 | private int randomnumber(int min, int max) { Random rnum = new Random(); return rnum.Next(min, max); } |
在要使用随机数的位置使用上述函数。假设您想在文本框中使用它。
1 | textBox1.Text = randomnumber(0, 999).ToString(); |
0是最小值,999是最大值。您可以将值更改为所需的任何值。
对不起,op确实需要一个随机的
1 | BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier)); |
为什么不使用
快速方便的内联,使用以下代码:
1 2 3 4 |
我总是有生成随机数的方法,这些方法有助于实现各种目的。我希望这也能帮助您:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class RandomGenerator { public int RandomNumber(int min, int max) { var random = new Random(); return random.Next(min, max); } public string RandomString(int size, bool lowerCase) { var builder = new StringBuilder(); var 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(); } } |
重复使用一个随机实例
1 2 3 4 5 6 7 8 9 10 11 12 | // 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
1 |
您还可以为
1 |