当前位置: 首页 > ds >正文

c#中生成随机数的三种方法

在 C# 中,生成随机数有多种方式,适用于不同场景。以下是5种主要方法及其对比:

计算机中不存在真正的 "随机数",我们生成的随机数本质是伪随机数—— 通过特定算法和初始条件(种子)计算出的序列。这些序列看似无序,但在相同种子下会完全重复,因此也被称为 "假随机"。

典型使用场景: 注册账号的验证码、唯一标识符生成、随机点名器、抽奖系统、游戏中的随机事件等。

1. 使用 Random 类(基础随机数)

特点:基于种子的伪随机数生成器,性能较高,适合普通随机场景。

示例代码

// 创建 Random 实例(默认使用时间戳作为种子)
Random random = new Random();
​
// 生成整数:[minValue, maxValue)
int randomInt = random.Next(1, 101);  // 生成 1 到 100 之间的随机整数
​
// 生成浮点数:[0.0, 1.0)
double randomDouble = random.NextDouble();  // 生成 0.0 到 1.0 之间的随机小数

注意事项

  • 种子问题:短时间内创建多个Random实例可能生成相同序列(因时间种子相同)。

    // 错误示例:每次循环创建新实例,可能生成相同随机数
    for (int i = 0; i < 5; i++) {Console.WriteLine(new Random().Next(100)); // 可能输出重复值
    }

  • 解决方案:复用单个 Random 实例。

  • 生成随机字符: 利用 ASCII 码范围生成 a-z 的随机字符串(97-122 对应小写字母):

    Random random5 = new Random();
    string result = "";
    for (int i = 0; i < 4; i++)
    {char c = (char)random5.Next(97, 123); // 生成97-122的随机数,转换为字符result += c;
    }
    Console.WriteLine(result); // 例如:"kqzx"

2. 使用 System.Random.Shared(线程安全版本)

特点:.NET 6+ 引入的静态线程安全随机数生成器,无需手动同步。

示例代码

// 生成线程安全的随机数
int safeRandomInt = Random.Shared.Next(1, 101);  // 线程安全的整数
double safeRandomDouble = Random.Shared.NextDouble();  // 线程安全的小数

优势

  • 无需担心多线程竞争问题,性能优于手动加锁的 Random

  • 适用于多线程环境(如并行计算)。

3. 使用 System.Security.Cryptography.RandomNumberGenerator(加密安全随机数)

特点:使用操作系统的加密随机数生成器,生成高质量随机数,适用于安全敏感场景(如密码、令牌生成)。

using System.Security.Cryptography;
​
// 生成加密安全的随机整数
byte[] buffer = new byte[4];  // 4字节 = 32位整数
using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {rng.GetBytes(buffer);  // 填充随机字节int secureRandomInt = BitConverter.ToInt32(buffer, 0);Console.WriteLine(Math.Abs(secureRandomInt % 100));  // 转换为 0-99 的整数
}
​
// 更简便的写法(.NET 6+)
int secureInt = RandomNumberGenerator.GetInt32(1, 101);  // 直接生成 1-100 的整数

适用场景

  • 密码学相关场景(如生成加密密钥)。

  • 安全令牌、验证码生成。

4. GUID(全球唯一标识符)

GUID(Globally Unique Identifier)是 128 位的唯一标识符,通过系统时间、硬件 ID 等多维度信息计算生成,重复概率极低(可视为全球唯一)。

核心特点:
  • 格式:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx(32 位十六进制数,含连字符),例如:6F9619FF-8B86-D011-B42D-00C04FC964FF

  • 生成方式:直接调用Guid.NewGuid()静态方法。

适用场景:

生成产品密钥、订单号、数据库主键、分布式系统中的唯一标识等。

Console.WriteLine(Guid.NewGuid()); 
// 输出示例:a27fc3ff-f785-4522-bced-7c0f24f0d0e8

5. RNGCryptoServiceProvider(加密级随机数)

属于加密安全的随机数生成器,基于操作系统底层的加密算法,生成高质量随机数,适用于安全性要求极高的场景。

核心用法:

通过字节数组接收随机数据,可转换为字符串或数值使用:

// 创建加密随机数生成器实例
using (RNGCryptoServiceProvider rcsp = new RNGCryptoServiceProvider())
{byte[] bytes = new byte[10]; // 指定随机数长度(10字节)rcsp.GetBytes(bytes); // 生成随机字节并填充到数组Console.WriteLine(BitConverter.ToString(bytes)); // 输出示例:3A-7B-2D-...(十六进制格式,以连字符分隔)
}
特点:
  • 随机性强:基于硬件或系统环境的熵值(不可预测性更高)。

  • 线程安全:支持多线程环境。

  • 性能较低:因加密算法复杂,生成速度慢于Random

适用场景:

密码加密、令牌生成、敏感数据加密密钥等安全敏感场景。

方法对比

方法性能线程安全随机性质量适用场景
Random普通(伪随机)游戏、随机排序、普通模拟
System.Random.Shared普通(伪随机)多线程环境下的普通随机需求
RandomNumberGenerator加密安全(真随机)密码学、安全令牌、敏感数据
GUID极高(近乎唯一)唯一标识(订单号、主键等)
RNGCryptoServiceProvider极高(加密级)安全场景(密码、密钥等)

总结

  • 普通场景:使用 Random 并复用实例。

  • 多线程场景:使用 System.Random.Shared

  • 安全敏感场景:使用 RandomNumberGenerator

补充说明

  1. Random的扩展用法: 生成随机字符除了通过 ASCII 码(97-122 对应 a-z),还可直接从字符集抽取:

    string chars = "qwertyuiopasdfghjklzxcvbnm";
    Random ran = new Random();
    string res = "";
    for (int i = 0; i < 4; i++)
    {res += chars[ran.Next(chars.Length)]; // 从字符集中随机取字符
    }

    洗牌算法:

  2. GUID的唯一性: GUID 的唯一性基于 "概率极低",理论上存在重复可能,但实际应用中可视为绝对唯一,无需担心冲突。

  3. .NET Core/.NET 5 + 的新选择: 对于加密随机数,推荐使用RandomNumberGenerator(.NET 6+)替代RNGCryptoServiceProvider(已过时),用法更简洁。

    // .NET 6+ 推荐写法
    byte[] bytes = new byte[10];
    RandomNumberGenerator.Fill(bytes); // 填充随机字节

http://www.xdnf.cn/news/15343.html

相关文章:

  • pgsql模板是什么?
  • Kafka——聊聊Kafka的版本号
  • 【理念●体系】从零打造 Windows + WSL + Docker + Anaconda + PyCharm 的 AI 全链路开发体系
  • 1Panel V1 无缝升级到 V2 版本 实现多个 PHP 网站共享一个容器
  • Spring Boot整合MyBatis+MySQL实战指南(Java 1.8 + 单元测试)
  • AIStarter新版重磅来袭!永久订阅限时福利抢先看
  • ARM架构CPU的市场和生态
  • 使用云虚拟机搭建hadoop集群环境
  • Claude Code是什么?国内如何使用到Claude Code?附国内最新使用教程
  • 四、神经网络——正则化方法
  • 喷涂机器人cad【1张】+三维图+设计说明书+降重
  • redis数据结构和数据类型
  • vector之动态二维数组的底层
  • 2025年亚太中文赛B题第一版本超详细解题思路
  • C++:非类型模板参数,模板特化以及模板的分离编译
  • Java大厂面试故事:谢飞机的互联网医疗系统技术面试(Spring Boot、MyBatis、Kafka、Spring Security、AI等)
  • FastAPI + SQLAlchemy (异步版)连接数据库时,对数据进行加密
  • 【字节跳动】数据挖掘面试题0016:解释AUC的定义,它解决了什么问题,优缺点是什么,并说出工业界如何计算AUC。
  • UE5多人MOBA+GAS 18、用对象池来设置小兵的队伍的生成,为小兵设置一个目标从己方出生点攻打对方出生点,优化小兵的血条UI
  • (补充)RS422
  • 【每日刷题】x 的平方根
  • 2D下的几何变换(C#实现,持续更新)
  • Elasticsearch混合搜索深度解析(下):执行机制与完整流程
  • 【AI News | 20250710】每日AI进展
  • 2025年DevSecOps工具全景图:安全左移时代的国产化突围
  • 深入探索Kafka Streams:企业级实时数据处理实践指南
  • 11. TCP 滑动窗口、拥塞控制是什么,有什么区别
  • 8-day06预训练模型
  • 揭示张量分析的强大力量:高级研究的基础-AI云计算拓展核心内容
  • Django老年健康问诊系统 计算机毕业设计源码32407