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

How do I generate a random integer in C#?

提问人:Rella 提问时间:4/25/2010 最后编辑:ADJenksRella 更新时间:3/8/2023 访问量:3038387

问:

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

C# 随机

评论

2赞 Mafii 7/12/2022
请参阅此答案,了解当前(也是最简单的)加密安全解决方案
0赞 Matilda Smeds 4/25/2023
Random.Shared 是当前在服务器端使用的方式。在这样一个用例中,加密安全性是必需的,在这个用例中,单个用户可以通过观察生成的数字序列来推断生成器的内部状态,并且还知道他们试图预测其值的生成数字的相对位置。

答:

75赞 Joren 4/25/2010 #1
Random r = new Random();
int n = r.Next();

评论

3赞 nilon 10/12/2020
这似乎是一个被低估的有价值的回应!
3赞 Eike 11/12/2021
@nilon 好吧,根据 OP 或像我这样的随机读者想要什么,这可能是一个被高估的回应。在我的书中,int 介于 int 之间。MinValue 和 int。MaxValue,但此调用(根据文档)从不发出负数。
4赞 Joren 11/20/2021
@Eike 由于 OP 没有提供任何细节,我也觉得没有必要写一整篇博文。 🤷 ♂️
129赞 Fyodor Soikin 4/25/2010 #2

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

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

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

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

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

所以不要用这段代码来生成一系列随机数。

评论

45赞 Bevan 4/25/2010
-1:默认种子基于时间;在一个循环中执行此操作,你会得到非常非随机的结果。您应该创建一个生成器并将其用于所有数字,而不是每次都使用单独的生成器。
27赞 Fyodor Soikin 4/25/2010
嘿,这不公平。问题是如何生成随机 int 数。没有提到循环或系列。
28赞 Bevan 4/25/2010
好吧,公平点。撤销。不过,我仍然认为不循环使用是很重要的一点。new Random()
0赞 vapcguy 2/15/2020
对于那些将来遇到这种情况的人来说,现在应该很明显了,但我只想指出一下;答案已更新为这一点,不要在循环中将其用于多个值。
3029赞 Guffa 4/25/2010 #3

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

评论

11赞 Junior Mayhé 2/11/2018
为了重用它,您可以在初始化代码时将其声明为和/或设置一次。rndstatic
11赞 Guffa 2/14/2018
@JuniorM:是的,你可以使它是静态的来重用它,但你必须小心,这样你就不会从多个线程访问它,因为它不是线程安全的(对于任何没有专门成为线程安全的类来说都是常见的)。
47赞 Daniel García Rubio 6/27/2018
我认为添加一个免责声明,说明这在加密上是不安全的,因为这是一个流行的问题,以防万一有人盲目地尝试用......Random
3赞 Jesse C. Slicer 10/9/2019
很好的答案。有一些很好的“增强功能”可以使你的随机性更加健壮:ericlippert.com/2019/02/04/fixing-random-part-2codeblog.jonskeet.uk/2009/11/04/revisiting-randomnessRandom
3赞 dev27 3/10/2020
如果有人感到困惑,包括 1 个,不包括 13 个。即下限是包容性的rnd.Next(1,13)
22赞 mbcrump 4/25/2010 #4

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

using MiscUtil;
...

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

评论

34赞 Andreas Rejbrand 4/25/2010
我刚刚看了一下源代码,这个函数使用完全相同的随机数引擎,即 C# 中的“包含”引擎,但确保所有调用都使用相同的“种子”/“母对象”。(很抱歉,我不了解 C# 术语。但我的观点是,这个函数并没有比标准函数产生任何更好的随机数。
6赞 Phill Healey 10/15/2014
任何事情都不可能是“真正随机的”,因为总有一些限制因素或偏见,这些因素或偏见是其存在所固有的。你没听科学课老师的话吗?;-)
0赞 The Mitra Boy 8/21/2015
比方说,根据他的说法,这是“真正的随机”
275赞 Pankaj Mishra 10/4/2010 #5

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

//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);
    }
}

评论

6赞 Chris 10/4/2010
这不就是@Guffa 6个月前在回答中所说的吗?“如果创建的新实例在时间上太近,它们将产生相同系列的随机数”
5赞 Pankaj Mishra 10/4/2010
@Chris-你说的没错。在这方面,我提供了它的实现。我认为这是一个很好的方法。它效果更好。
25赞 Guffa 2/26/2013
这是一个实现,用于同步代码以从 seval 线程使用。这对于多线程应用程序来说是件好事,但对于单线程应用程序来说却是浪费时间。
0赞 testing 9/13/2017
@SeanWorle:首先,我用Guffa的方法尝试了一下。然后我尝试存储相同的对象。在这两种情况下,我都得到了相同的随机数。在Pankaj的方法下,它没有发生。也许这是随机的,但我现在对此表示怀疑。我正在从不同的线程中查询同一秒内的随机数。Random
4赞 Sean Worle 9/14/2017
@testing:我同意 Pankaj 的方法是正确的。我要说的是,可以简化为: //获取随机数的函数 private static readonly Random getrandom = new Random();public static int GetRandomNumber(int min, int max) { lock(getrandom ) { // 同步返回 getrandom.下一个(最小值,最大值);} }
15赞 JebaDaHut 3/28/2014 #6

从这里修改答案。

如果您有权访问兼容 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>");
4赞 user3773367 6/25/2014 #7
Random rand = new Random();
int name = rand.Next()

将所需的任何值放在第二个括号中 确保你已通过编写 prop 和 double tab 来设置名称以生成代码

评论

0赞 Sнаđошƒаӽ 3/1/2018
为什么选择道具和双标签?你是说没有那个键盘快捷键,这是属性的简写,你的代码将无法工作?
7赞 Ojonugwa Jude Ochalifu 8/22/2014 #8

虽然这没关系:

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

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

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

因此,如果我希望我的随机数介于 5 和 15 之间,我会这样做

int randomNumber = random.Next(5, 16)
7赞 AskethZ 12/7/2014 #9

这是我使用的类。工作原理类似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);
    }
}

评论

0赞 Gordon Bell 7/27/2016
GenerateRandom 类永远不会返回数字 666,只会返回 665。这是对 Random.Next 最大值的常见误解(功能)。
18赞 Proximo 5/20/2015 #10

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

这些解决方案都不够好。我需要在快速 for 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); 
}

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

评论

8赞 Markus 10/12/2015
Guid 不是随机的,它不是一个好的种子。GUID 不保证随机性,而是保证唯一性。stackoverflow.com/questions/2621563/......
3赞 Proximo 10/12/2015
Guid 是一粒好种子。我只使用 Guid 中的数字。亲自尝试该方法。把它放在一个长循环中,自己看看结果。
2赞 Proximo 10/12/2015
嗯,转念一想..种子根本不需要。更新答案
3赞 JCisar 8/20/2016
更新的好点。我什至没有想过要把它变成一个静态场,这种方式效果更好,更干净。
2赞 Hector 10/10/2017
这个答案存在一些问题。首先,GUID 不是一个很好的种子源 - 仅仅因为它看起来是随机的并不意味着它是随机的。它可能足以满足您的个人需求。其次,Random 类不是线程安全的。您需要在每个线程实例化一次。
15赞 Anshita Arya 7/22/2015 #11

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

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

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

-2赞 Hani Mehdi 9/9/2015 #12

尝试以下简单步骤来创建随机数:

创建函数:

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

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

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

0 是最小值,999 是最大值。您可以将值更改为所需的任何值。

评论

0赞 MOnsDaR 4/13/2016
当它使用系统时间作为种子时,当多次紧密调用时,这将返回相同的数字......
2赞 Gordon Bell 7/27/2016
randomNumber(0, 999) 永远不会返回 999。最大值不包括在内。这是对 Random.Next 最大值的常见误解(功能)。
25赞 Mohamed Ali 11/1/2015 #13

创建一个 Random 对象

Random rand = new Random();

并使用它

int randomNumber = rand.Next(min, max);

你不必每次都需要一个随机数时都初始化,启动一个随机数,然后在循环中根据需要多次使用它new Random()

评论

7赞 Hans Kesting 4/7/2017
new Random()使用当前分时作为种子。当您在同一毫秒内实例化多个实例(而不是 tick)时,您将返回相同的值。
11赞 Oren Melzer 8/17/2018
这很糟糕。DateTime.Now.Millisecond(与 DateTime.Now.Ticks 不同)是介于 0 和 999 之间的数字。如果你为每个随机数创建一个新的随机数,你只有 1000 种可能性。
0赞 Enigmativity 5/15/2020
24 个人在投票支持这个答案时在想什么......?
41赞 joordan831 12/19/2015 #14

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

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);
}
4赞 Stefano Lonati 3/14/2016 #15

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

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

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

-1赞 Recomer 3/20/2016 #16

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

评论

0赞 Gordon Bell 7/27/2016
实际上 int randomNumber = Random.Range(start_range, end_range + 1)
5赞 Phillip Ngan 9/1/2016
Random.Range() 存在吗?我在MSDN文档中找不到它。
0赞 Lance U. Matthews 2/20/2022
这似乎是特定于 Unity 的。如果是这样,说明这一点并解释它与 System.Random 的比较会很有帮助。
5赞 John Alexiou 4/9/2016 #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; }
}

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

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; }
}

评论

0赞 John Alexiou 4/11/2016
那么,您如何安全地选择种子呢?
0赞 Millie Smith 4/11/2016
首先,如果您的对象创建间隔 10 毫秒,则生成的随机数与默认种子不同。其次,你可以捣碎你所拥有的任何随机环境或处理数据来获得种子。然后是权衡是想要一个最有可能开始重复的一长串数字,还是多个流,即使两个流最终是相同的。如果您担心安全性,无论如何都是一个更好的选择。RNGCryptoServiceProvider
0赞 John Alexiou 4/11/2016
如果有一个带有小α粒子放射源和探测器(烟雾探测器的工作原理)的随机化芯片,以便根据放射性衰变(非常随机)随机化数字,那就太酷了。
404赞 Shivprasad Koirala 6/14/2016 #18

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

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

我鼓励您观看我制作的这个视频,该视频深入探讨了使用 C# 的随机性哲学 https://www.youtube.com/watch?v=tCYxc-2-3fY

首先让我们了解随机性的哲学。当我们告诉一个人在红色、绿色和黄色之间做出选择时,内部会发生什么。是什么让一个人选择红色、黄色或绿色?

c# Random

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

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

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

c# Random

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

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

c# Random

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

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

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

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 随机数。

评论

15赞 Bernhard 11/21/2017
不应该只有 byte[5] [4] 因为 ToInt32 只解析 4 个字节?
14赞 Elton 12/19/2018
知道这些班级住在哪里总是很有帮助的。System.Security.Cryptography (系统安全密码学)
11赞 dzitkowskik 10/18/2019
建议使用而不是调用构造函数,因为它并非在所有平台上都可用。RandomNumberGenerator.Create()RNGCryptoServiceProvider
0赞 Nùménor 1/30/2020
我只想精确地确定 SecureRandom 是伪随机生成。
1赞 user2150989 3/24/2020
由于种子的随机性增加,是否可以在每次需要生成随机数时创建新的 RNGCryptoServiceProvider 对象,或者创建一个 RNGCryptoServiceProvider 对象并在需要生成随机数时重用它,就像使用 Random 类一样?
-4赞 Muhammad Awais 8/8/2016 #19
 int n = new Random().Next();

您还可以为函数提供最小值和最大值。喜欢:Next()

 int n = new Random().Next(5, 10);
3赞 ReRoute 3/17/2017 #20
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);

评论

1赞 Robert Columbia 8/22/2018
虽然此代码可以回答问题,但最好解释如何解决问题并提供代码作为示例或参考。纯代码答案可能会令人困惑且缺乏上下文。
-4赞 Zolfaghari 5/10/2018 #21

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

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

// for example unique name
strName += "_" + new Random().Next(100, 999);
2赞 auto9817 5/15/2018 #22

我假设你想要一个均匀分布的随机数生成器,如下所示。大多数编程语言(包括 C# 和 C++)中的随机数在使用它们之前没有正确洗牌。这意味着您将一遍又一遍地获得相同的数字,这并不是真正的随机。为了避免一遍又一遍地绘制相同的数字,您需要一个种子。通常,对于此任务,时间滴答是可以的。请记住,如果您每次都使用相同的种子,您将一遍又一遍地获得相同的数字。因此,请始终尝试使用不同的种子。时间是种子的良好来源,因为它们总是在变动。

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

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

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)

随机高斯变量

-2赞 PatsonLeaner 5/15/2018 #23

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

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();  
    }  
}
4赞 Davit Tvildiani 5/26/2018 #24

对于强随机种子,我总是使用 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);
        }
    }
}

评论

0赞 Lance U. Matthews 2/20/2022
您正在使用一个随机数生成器来获取另一个随机数生成器的种子?如果你需要一个“强”种子,那么你难道不想要(加密)强数字输出吗?为什么不在这一点上直接用于所有东西呢?RNGCryptoServiceProvider
-1赞 Ankit Agarwal 6/14/2018 #25

重复使用一个 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

评论

0赞 Brad M 1/25/2019
Random不是线程安全类。如果创建单个实例,则应在锁定机制后面限制对该实例的访问。
3赞 Ciro Corvino 12/8/2018 #26

对不起,OP 确实需要一个随机的 int 值,但为了分享知识的简单目的,如果你想要一个随机值,你可以使用以下语句:BigInteger

BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));

评论

1赞 Lance U. Matthews 2/20/2022
我认为您最好使用或使用重复调用来构建随机数字并解析它。这种(ab)用法是非正统的,几乎可以保证返回天文数字(所以不是真正的“随机”)。此外,文档建议“......应用程序不会将该方法用于加密目的。byte[] bytes = new byte[byteCount]; random.NextBytes(bytes); BigInteger value = new BigInteger(bytes);Random.Next((int) '0', ((int) '9') + 1)stringGuidNewGuid
12赞 Lucca Ferri 9/26/2019 #27

仅供将来参考。

如果使用的是 .NET Core,则多个随机实例不会像以前那样危险。我知道这个问题是 2010 年的,但由于这个问题很老,但有一些吸引力,我认为记录变化是一件好事。

你可以参考我刚才提出的这个问题:

Microsoft 是否更改了随机默认种子?

基本上,他们已将默认种子从 更改为 ,因此如果您创建 2 个 Random 实例,它不应显示相同的数字(1:4 亿)。Environment.TickCountGuid.NewGuid().GetHashCode()

可以在此处查看文件与 .NET Framework/.NET Core (2.0.0+) 的差异:https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d

它不像 RNGCryptoServiceProvider 安全,但至少它不会给你奇怪的结果。


按@Enigmativity:

这现在已经过时了。对使用 Guids 有相当大的反对。代码现在是 Interop.GetRandomBytes((byte*)&result, sizeof(int));

评论

2赞 Enigmativity 5/15/2020
这现在已经过时了。对使用 Guids 有相当大的反对。代码现在是 .Interop.GetRandomBytes((byte*)&result, sizeof(int));
4赞 Jessie Lesbian 10/28/2019 #28

如果您希望 CSRNG 生成最小值和最大值之间的随机数,这是为您准备的。它将使用安全的随机种子初始化类。Random

    class SecureRandom : Random
    {
        public static byte[] GetBytes(ulong length)
        {
            RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
            byte[] bytes = new byte[length];
            RNG.GetBytes(bytes);
            RNG.Dispose();
            return bytes;
        }
        public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
        {

        }
        public int GetRandomInt(int min, int max)
        {
            int treashold = max - min;
            if(treashold != Math.Abs(treashold))
            {
                throw new ArithmeticException("The minimum value can't exceed the maximum value!");
            }
            if (treashold == 0)
            {
                throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
            }
            return min + (Next() % treashold);
        }
        public static int GetRandomIntStatic(int min, int max)
        {
            int treashold = max - min;
            if (treashold != Math.Abs(treashold))
            {
                throw new ArithmeticException("The minimum value can't exceed the maximum value!");
            }
            if(treashold == 0)
            {
                throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
            }
            return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
        }
    }
3赞 Matt Parkins 7/18/2020 #29

有许多实用工具函数或服务可以更好地以与 System.Random 相同的方式进行缓存,因此它适合于泛型实现:

static public class CachedService<T> where T : new() {
    static public T Get { get; } = new T();
}

用于随机(或类似):

CachedService<System.Random>.Get.Next(999);

评论

0赞 Björn Larsson 8/23/2022
这似乎是不必要的复杂。为什么需要缓存?
0赞 Matt Parkins 8/30/2022
我缓存了相当多的服务,我只会像使用单例一样使用 - 对我有用。
19赞 Misha Zaslavsky 12/20/2021 #30

如其他答案中所述,一个好的安全方法是使用安全的加密生成器。这里的所有示例都显示了与我建议的解决方案相比,编写长代码的用法。RNGCryptoServiceProvider

使用编写在加密 API 之上的 RandomNumberGenerator。它与相同的随机性一样安全。RNGCryptoServiceProvider

// Gives a random number for the integer range.
// You can simply update the parameters as your needs.
RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);

评论

5赞 Lance U. Matthews 2/20/2022
从 .NET 6 开始,已标记并建议改用。RNGCryptoServiceProvider[Obsolete()]RandomNumberGenerator
-2赞 Masiha 2/17/2022 #31
Random r=new Random();
int Numbers=r.next(min value, max value);

评论

1赞 Lance U. Matthews 2/20/2022
该方法被命名为 ,而不是 ,因此不会编译。此外,上限参数是互斥的,因此将返回的最大数字实际上是 。 对于存储单个数字的变量来说,也是一个不好的名字。最后,也是最重要的一点是,该类的这种基本用法已被许多其他答案所涵盖。Nextnextr.Next(minValue, maxValue);maxValue - 1NumbersRandom
-2赞 user21327910 3/8/2023 #32

该类用于生成伪随机数。 一个例子可能是这样的:Random

public int GenRandom(int minimum, int maximum)
{
    Random random = new Random();
    int result = random.Next(minimum - 1, maximum + 1);
    return result;
}

添加了最小值和最大值,因为该函数永远无法达到 和 .1Next(int, int)minimummaximum

再看看这个,将是一个随机数猜测者:

class Program
{
    static void Main(string[] args)
    {
        int i = 0;
        while (true)
        {
            if (i < 1)
            {
                Console.Write("Minimum value: ");
                int min = int.Parse(Console.ReadLine());
                Console.Write("Maximum value: ");
                int max = int.Parse(Console.ReadLine());
                Random random = new Random();
            }
            int randomNumber = random.Next(min, max);
            Console.Write("Enter a guess: ");
            if (int.Parse(Console.ReadLine()) == randomNumber)
            {
                Console.WriteLine("Congrats! You won!");
                Console.ReadKey();
                return;
            }
            else
                Console.WriteLine("Hmm, give it another guess!"); return;
        }
    }
}
7赞 Misha Zaslavsky 3/8/2023 #33

在 .NET 6 中,可以使用 Random.Shared

int random = Random.Shared.Next();

在 .NET 8 预览版中,该类添加了许多新的缺失方法,例如随机随机数组等。