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

问:

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

答1:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

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

例子:

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

为了重用它,您可以将 rnd 声明为 static 和/或在初始化代码时只设置一次。

@JuniorM:是的,您可以将其设为静态以重用它,但是您必须小心,以免从多个线程访问它,因为它不是线程安全的(对于任何未专门设为线程安全的类来说都是如此) )。

我认为添加免责声明会很有用,即这不是加密安全的,因为这是一个流行的问题,以防万一有人盲目地尝试使用 Random 进行加密......

优秀的答案。 Random 有一些很好的“增强”,可以使您的随机性更加健壮: ericlippert.com/2019/02/04/fixing-random-part-2 和 codeblog.jonskeet.uk/2009/11/04/revisiting-randomness 。

如果有帮助, var number = Random.Range(1, 254);来自统一交换:answers.unity.com/questions/308513/random-number-generator.html

答2:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

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

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

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

https://i.stack.imgur.com/nsoQL.png

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

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

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

https://i.stack.imgur.com/vQ9y5.png

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

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

https://i.stack.imgur.com/JJ93T.png

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

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

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

不应该是你的 byte[5] only [4] 因为 ToInt32 只解析 4 个字节?

了解这些课程的位置总是有帮助的。系统安全密码学

建议使用 RandomNumberGenerator.Create() 而不是调用 RNGCryptoServiceProvider 的构造函数,因为它并非在所有平台上都可用。

我只想准确地说 SecureRandom 是伪随机生成。

由于种子的随机性增加,是否可以在每次需要生成随机数时创建新的 RNGCryptoServiceProvider 对象,或者创建一个 RNGCryptoServiceProvider 对象并在需要生成随机数时重用它更好,如应该用 Random 类来完成吗?

答3:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

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

这不是@Guffa 6 个月前在他的回答中所说的吗? “如果您创建新实例的时间太近,它们将产生相同系列的随机数”

@Chris-你说的对。在此,我提供了它的实现。我认为这是一个很好的方法。它工作得更好。

这是一个同步代码以供 seval 线程使用的实现。这对于多线程应用程序来说很好,但对于单线程应用程序来说是浪费时间。

@SeanWorle:首先,我尝试了 Guffa 的方法。然后我尝试存储相同的 Random 对象。在这两种情况下,我都得到了相同的随机数。使用 Pankaj 的方法并没有发生。也许这是随机,但我现在对此表示怀疑。我在同一秒内从不同的线程查询随机数。

@testing:我同意Pankaj 的方法是正确的。我说的是可以简化成这样://获取随机数的函数 private static readonly Random getrandom = new Random(); public static int GetRandomNumber(int min, int max) { lock(getrandom ) { // 同步返回 getrandom.Next(min, max); } }

答4:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

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

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

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

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

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

-1:默认种子是基于时间的;循环执行此操作,您将获得非常非随机的结果。您应该创建一个生成器并将其用于所有数字,而不是每次都使用单独的生成器。

嘿,这不公平。问题是如何生成随机整数。没有提到循环或系列。

好的,公平点。撤销。不过,我仍然认为不要在循环中使用 new Random() 是很重要的一点。

对于那些将来遇到这个问题的人来说,现在应该很明显了,但我只是指出来;答案已在这一点上更新,不要在循环中将其用于多个值。

答5:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

这似乎是一个被低估的有价值的回应!

@nilon好吧,这取决于OP-或像我这样的随机读者-想要什么,这可能是一个被高估的回应。在我的书中,int 介于 int.MinValue 和 int.MaxValue 之间,但这个调用(根据文档)从不发出负数。

@Eike由于OP没有提供任何细节,我也觉得没有必要写一篇完整的博客文章。 🤷‍♂️

答6:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

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

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

答7:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

创建一个随机对象

Random rand = new Random();

并使用它

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

您不必每次需要一个随机数时都初始化 new Random(),启动一个 Random 然后在循环或其他任何内容中根据需要多次使用它

new Random() 使用当前报价作为种子。当您在同一毫秒内(而不是滴答声)实例化多个实例时,您将获得相同的返回值。

这是非常糟糕的。 DateTime.Now.Millisecond(与 DateTime.Now.Ticks 不同)是一个介于 0 和 999 之间的数字。如果您为每个随机数创建一个新的,那么您将只有 1000 种可能性。

24 个人在投票赞成这个答案时是怎么想的……?

答8:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

using MiscUtil;
...

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

我刚刚查看了源代码,该函数使用完全相同的随机数引擎,即 C# 中“包含”的引擎,但确保所有调用都使用相同的“种子”/“母对象”。 (很抱歉,我不知道 C# 术语。但我的意思是,这个函数不会产生比标准函数更好的随机数。)

任何事物都不可能是“真正随机的”,因为总是存在一些限制因素或偏见,这是其存在所固有的。你在科学课上没听老师的话吗? ;-)

比方说,在他看来,这是“真正随机的”

答9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

我已经尝试了所有这些解决方案,不包括 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); 
}

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

Guid 不是随机的,它不是一个好种子。 GUID 不保证随机性,它保证唯一性。 stackoverflow.com/questions/2621563/…

Guid是一粒好种子。我只使用 Guid 中的数字。自己试试这个方法。把它放在一个很长的 for 循环中,然后自己查看结果。

嗯,再想一想.. 根本不需要种子。更新答案

更新的重点。我什至没有想过让它成为一个静态字段,这种方式效果更好,更干净。

这个答案有一些问题。首先,GUID 不是一个很好的种子源——仅仅因为它看起来是随机的并不意味着它是。它可能足以满足您的个人需求。其次, Random 类不是线程安全的。您需要为每个线程实例化一次。

答10:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

如果您想要真正的随机数,我们可以获得的最接近的是“安全伪随机生成器”,它可以通过使用 C# 中的 Cryptographic 类(例如 RNGCryptoServiceProvider)生成。

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

答11:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

来自 here 的修改答案。

如果您可以访问与 Intel 安全密钥兼容的 CPU,则可以使用以下库生成真正的随机数和字符串:https://github.com/JebteK/RdRand 和 https://www.rdrand.com/

只需从 here 下载最新版本,包括 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(, "");

原文链接:https://www.huntsbot.com/qa/VdLK/how-do-i-generate-a-random-integer-in-c?lang=zh_CN&from=csdn

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值