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

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

技术背景

在C#开发中,经常会遇到需要生成随机整数的场景,比如游戏开发中的随机事件、测试用例中的随机数据生成等。然而,计算机通过确定性过程计算出的数字,从定义上来说并非真正的随机。C#提供了多种生成随机整数的方式,每种方式都有其特点和适用场景。

实现步骤

使用 Random 类生成伪随机数

Random 类是C#中常用的生成随机数的类,它生成的是伪随机数。以下是使用示例:

1
2
3
4
Random rnd = new Random();
int month = rnd.Next(1, 13); // 创建一个1到12之间的数字
int dice = rnd.Next(1, 7); // 创建一个1到6之间的数字
int card = rnd.Next(52); // 创建一个0到51之间的数字

如果需要生成多个随机数,建议保持 Random 实例并重复使用,因为如果在短时间内创建多个 Random 实例,由于随机数生成器是根据系统时钟播种的,它们可能会产生相同的随机数序列。以下是一个封装的方法:

1
2
3
4
5
6
7
8
9
10
// 函数用于获取随机数
private static readonly Random getrandom = new Random();

public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // 同步
{
return getrandom.Next(min, max);
}
}

使用 RNGCryptoServiceProvider 类生成安全随机数

RNGCryptoServiceProvider 类使用操作系统的熵来生成种子,能生成更安全的随机数。以下是示例代码:

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

在 .NET 6 及以上版本使用 Random.Shared

在 .NET 6 中,可以使用 Random.Shared 来生成随机数:

1
int random = Random.Shared.Next();

使用 RandomNumberGenerator

RandomNumberGenerator 类基于加密 API 编写,和 RNGCryptoServiceProvider 一样安全且具有相同的随机性:

1
2
3
// 为整数范围生成一个随机数
// 可以根据需要更新参数
RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);

使用 Guid 作为种子

可以通过解析 Guid 中的数字部分作为种子来实例化 Random 类:

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

使用 Intel Secure Key 兼容 CPU

如果有兼容 Intel Secure Key 的 CPU,可以使用相关库生成真正的随机数和字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 检查是否为兼容的 CPU
bool isAvailable = RdRandom.GeneratorAvailable();

// 生成10个随机字符
string key = RdRandom.GenerateKey(10);

// 生成64个随机字符,适用于API密钥
string apiKey = RdRandom.GenerateAPIKey();

// 生成一个包含10个随机字节的数组
byte[] b = RdRandom.GenerateBytes(10);

// 生成一个随机无符号整数
uint i = RdRandom.GenerateUnsignedInt();

核心代码

使用 Random 类生成指定范围的随机数

1
2
Random random = new Random();
int randomNumber = random.Next(5, 16); // 生成5到15之间的随机数

使用 RNGCryptoServiceProvider 类生成安全随机数

1
2
3
4
5
6
7
8
9
using System.Security.Cryptography;
using System;

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

使用 Random.Shared 生成随机数(.NET 6 及以上)

1
int random = Random.Shared.Next();

最佳实践

  • 避免频繁创建 Random 实例:如果需要生成多个随机数,应保持一个 Random 实例并重复使用,避免在短时间内创建多个实例导致生成相同的随机数序列。
  • 根据需求选择合适的随机数生成方式:如果对随机数的安全性要求不高,可以使用 Random 类;如果需要生成安全的随机数,建议使用 RNGCryptoServiceProviderRandomNumberGenerator 类。
  • 使用静态随机生成器:在多类或多方法需要随机数的场景中,使用单个静态随机生成器,避免不同实例生成相同的随机数。

常见问题

为什么短时间内创建多个 Random 实例会生成相同的随机数?

Random 类默认使用系统时钟作为种子,由于时钟的分辨率有限,在短时间内创建多个 Random 实例会导致它们使用相同的种子,从而生成相同的随机数序列。

Random 类和 RNGCryptoServiceProvider 类生成的随机数有什么区别?

Random 类生成的是伪随机数,其种子是根据系统时钟生成的,容易被预测;而 RNGCryptoServiceProvider 类使用操作系统的熵来生成种子,生成的随机数更安全,难以被预测。

在 .NET Core 中,多个 Random 实例是否还会有问题?

在 .NET Core 中,Random 类的默认种子从 Environment.TickCount 改为 Guid.NewGuid().GetHashCode(),所以短时间内创建多个 Random 实例生成相同随机数的概率大大降低,但仍然不如 RNGCryptoServiceProvider 安全。


在C#中如何生成随机整数
https://119291.xyz/posts/2025-05-14.how-to-generate-random-integer-in-csharp/
作者
ww
发布于
2025年5月14日
许可协议