C# Random 随机数 全面解析
总目录
前言
一、Random 是什么?
1. 简介
表示伪随机数生成器,这是一种能够产生满足某些随机性统计要求的数字序列的算法。
public class Random
继承:Object → Random
2. 构造函数
3. 属性
4. 方法
二、Random 的使用
1. Next() 或 NextInt64()
Next 返回一个非负随机整数。
static void Main(string[] args)
{
var random=new Random();
for (int i = 0; i < 5; i++)
{
var num = random.Next();
Console.WriteLine($"{num}");
}
Console.ReadKey();
}
输出结果:
76862089
1371118149
1965820566
1160787942
1644846096
2. Next(Int32) 或 NextInt64(Int64)
- 返回一个小于所指定最大值的非负随机整数。
static void Main(string[] args)
{
var random=new Random();
for (int i = 0; i < 5; i++)
{
var num = random.Next(15);
Console.WriteLine($"{num}");
}
Console.ReadKey();
}
运行结果:
2
9
2
13
11
3. Next(Int32, Int32) 或 NextInt64(Int64, Int64)
- 返回在指定范围内的任意整数。
- 注意:生成的随机数 包括
minValue
,但是不包括maxValue
static void Main(string[] args)
{
var random=new Random();
for (int i = 0; i < 5; i++)
{
var num = random.Next(15,200);
Console.WriteLine($"{num}");
}
Console.ReadKey();
}
运行结果:
46
78
170
83
58
4. NextSingle() 和 NextDouble() 、Sample()
- 返回一个大于或等于 0.0 且小于 1.0 的随机浮点数。
- NextSingle() 支持 .NET 6/7/8/9
static void Main(string[] args)
{
var random=new Random();
for (int i = 0; i < 5; i++)
{
var num = random.NextDouble();
Console.WriteLine($"{num}");
}
Console.ReadKey();
}
运行结果:
0.241523597036267
0.0462926887191332
0.585451771312138
0.628924066493718
0.972035988686623
5. NextBytes(Byte[])
- 用随机数填充指定字节数组的元素。
static void Main(string[] args)
{
var random=new Random();
byte[] bytes = new byte[10];
random.NextBytes(bytes);
foreach (var item in bytes)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
运行结果:
82
94
151
251
134
195
217
150
157
129
6. Shuffle<T>(Span<T>)
- 执行跨度的就地洗牌。
7. Shuffle<T>(T[])
- 执行数组的就地洗牌。。
三、Random为啥是伪随机数
1. 伪随机数的原因
random是伪随机,同一秒创建的随机对象,所生成的随机队列是一样的,除非不是同一时间产生
static void Main(string[] args)
{
Random random = new Random();
Random random2 = new Random();
Place:
int num = random.Next(0, 11);
int num2 = random2.Next(0, 11);
Console.WriteLine($"num={num},num2={num2}");
Thread.Sleep(1000);
goto Place;
}
运行结果:
num=7,num2=7
num=7,num2=7
num=1,num2=1
num=8,num2=8
num=2,num2=2
num=7,num2=7
num=0,num2=0
由以上案例可知,在时间间隔极其接近的时候,生成的随机数是一样的。
2. 生成相对随机的随机数
1. 使用种子值
这里通过上面的案例我们发现:通过使用不同的种子值 初始化 Random 类是可以生成 不是完全一样的两个随机序列。那么现在问题就变成了,如何生成唯一的种子值。
- 方法1
public static int GenerateRandomSeed()
{
return unchecked((int)DateTime.Now.Ticks);
}
- 方法2
using System.Text.RegularExpressions;
public static int GenerateRandomSeed()
{
return Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
}
- 方法3(推荐)
public static int GenerateRandomSeed()
{
return Guid.NewGuid().GetHashCode();
}
- 方法4
using System.Security.Cryptography;
public static int GenerateRandomSeed()
{
byte[] bytes = new byte[4];
RNGCryptoServiceProvider rngCSP = new RNGCryptoServiceProvider();
rngCSP.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
调用和运行结果(随便选择一种种子值的生成方法):
2. 使用Thread.Sleep(1)
在两个Random 实例化中间增加一个时间为1 毫秒的 延迟即可。
四、Random 扩展与应用
1. 生成随机的字符
在某些情况下,随机数只能取一些特殊指定的值,如不连续的数字或指定的一些单词等,此时仅用 Random 无法达到要求,必须借助数组才能实现。
实现思路大概是这样:先把这些特殊的值存到数组中,然后把数组的长度作为 Random 的上限产生随机数,此随机数正是数组的下标,根据该下标取得数组的值。
- 封装成扩展方法来使用
public static class RandomExtension
{
public static string NextString(this Random random, string[] arr)
{
var index = random.Next(arr.Length);
return arr[index];
}
}
调用:
static void Main(string[] args)
{
Random random = new Random();
for (int i = 0; i < 5; i++)
{
var str = random.NextString(new string[] { "张三", "李四", "王五","赵六" });
//var str = random.NextString(new string[] { "黑", "黄", "绿","红" });
Console.WriteLine($"{str}");
}
Console.ReadKey();
}
运行结果:
张三
王五
王五
张三
张三
2. 生成随机的布尔值
- 封装成扩展方法来使用
public static class RandomExtension
{
public static bool NextBool(this Random random)
{
bool[] boolArr = new bool[] { true, false };
var index = random.Next(boolArr.Length);
return boolArr[index];
}
}
调用:
static void Main(string[] args)
{
Random random = new Random();
for (int i = 0; i < 1115; i++)
{
var str = random.NextBool();
Console.WriteLine($"{str}");
}
Console.ReadKey();
}
3. 生成指定范围内浮点随机数
- 生成指定范围内浮点随机数
double randomDouble = random.NextDouble() * 100; // 生成0到100之间的随机浮点数
Console.WriteLine(randomDouble);
// 生成特定范围内的随机浮点数
double rangeRandomDouble = random.NextDouble() * (maxValue - minValue) + minValue;
Console.WriteLine(rangeRandomDouble); // 假设maxValue和minValue是之前定义的变量
static void Main(string[] args)
{
var random=new Random();
int min = 100;
int max = 285;
for (int i = 0; i < 5; i++)
{
var num = random.NextDouble() * (max - min) + min;
Console.WriteLine($"{num}");
}
Console.ReadKey();
}
运行结果:
126.074954253191
203.064250968427
209.030935270261
208.824055366602
180.678236866686
封装成扩展方法:
public static class RandomExtension
{
public static double NextDouble(this Random random,double min, double max)
{
return (random.NextDouble() * (max - min) + min);
}
}
- 生成保留指定小数位数(例如 2 位)的随机数
public static class RandomExtension
{
public static double NextDouble(this Random random, double min, double max,int decimalPlace)
{
double randomNum = (random.NextDouble() * (max - min) + min);
return Convert.ToDouble(randomNum.ToString($"F{decimalPlace}"));
}
}
4. 生成一个随机字符串(支持英文大小写字母/数字混合)
public static class RandomExtension2
{
/// <summary>
/// 生成随机字符串
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="digits">字符串的长度</param>
/// <param name="number">是否包括数字</param>
/// <param name="lowercase">是否包含小写字母</param>
/// <param name="capital">是否包含大写字母</param>
/// <param name="special">是否包含特殊字符</param>
/// <returns></returns>
public static string GetRandomCharacters(this Random random, int digits = 10, bool number = true, bool lowercase = true, bool capital = true, bool special = false)
{
string CapitalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string LowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
string Numbers = "0123456789";
string SpecialCharacters = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
StringBuilder tmp = new StringBuilder();
string characters = (capital ? CapitalLetters : null) + (number ? Numbers : null) + (lowercase ? LowercaseLetters : null) + (special ? SpecialCharacters : null);
if (characters.Length < 1) return null;
for (int i = 0; i < digits; i++)
{
tmp.Append(characters[random.Next(characters.Length)].ToString());
}
return (tmp.ToString());
}
}
或
/// <summary>
/// 生成一个随机字符串。
/// </summary>
/// <param name="length">生成的字符串长度。</param>
/// <param name="useUppercase">是否包含大写字母。</param>
/// <param name="useLowercase">是否包含小写字母。</param>
/// <param name="useDigits">是否包含数字。</param>
/// <param name="useSpecialChars">是否包含特殊字符。</param>
/// <returns>生成的随机字符串。</returns>
public static string GenerateRandomString(this Random random, int length = 10, bool useUppercase = true, bool useLowercase = true, bool useDigits = true, bool useSpecialChars = false)
{
if (length <= 0)
throw new ArgumentException("长度必须大于零。", nameof(length));
// 定义字符集合
var charPool = new StringBuilder();
if (useUppercase) charPool.Append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (useLowercase) charPool.Append("abcdefghijklmnopqrstuvwxyz");
if (useDigits) charPool.Append("0123456789");
if (useSpecialChars) charPool.Append("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
if (charPool.Length == 0)
throw new ArgumentException("至少需要选择一种字符类型。");
// 生成随机字符串
var chars = new char[length];
for (int i = 0; i < length; i++)
{
int index = random.Next(0, charPool.Length);
chars[i] = charPool[index];
}
return new string(chars);
}
调用:
static void Main(string[] args)
{
Random random = new Random();
for (int i = 0; i < 5; i++)
{
var str = random.GenerateRandomString(useSpecialChars:true);
Console.WriteLine($"{str}");
}
Console.ReadKey();
}
运行结果:
Bz4./WFDM,
mNl0]`p3sL
K&|Vgh"HXV
njXyt3,uit
Ii!fQKm/-;
可以通过方法中的参数配置,生成的字符串的长度以及是否包含大小写字母,特殊字符等,但是并不能保证,一定包含,因此该方法有优化空间。
优化后:
public static class RandomExtension
{
/// <summary>
/// 生成一个随机字符串。
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="length">生成的字符串长度。</param>
/// <param name="useUppercase">是否包含大写字母。</param>
/// <param name="useLowercase">是否包含小写字母。</param>
/// <param name="useDigits">是否包含数字。</param>
/// <param name="useSpecialChars">是否包含特殊字符。</param>
/// <returns>生成的随机字符串。</returns>
public static string GenerateRandomString(this Random random, int length = 10, bool useUppercase = true, bool useLowercase = true, bool useDigits = true, bool useSpecialChars = false)
{
string CapitalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string LowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
string Numbers = "0123456789";
string SpecialCharacters = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
if (length <= 0)
throw new ArgumentException("长度必须大于零。", nameof(length));
// 定义字符集合
var charPool = new StringBuilder();
var requiredChars = new StringBuilder();
if (useUppercase)
{
charPool.Append(CapitalLetters);
// 确保至少有一个大写字母,固定值A
//requiredChars.Append('A');
// 确保至少有一个大写字母,随机值
requiredChars.Append(CapitalLetters[random.Next(CapitalLetters.Length)]);
}
if (useLowercase)
{
charPool.Append(LowercaseLetters);
// 确保至少有一个小写字母,固定值a
//requiredChars.Append('a');
// 确保至少有一个小写字母,随机值
requiredChars.Append(LowercaseLetters[random.Next(LowercaseLetters.Length)]);
}
if (useDigits)
{
charPool.Append(Numbers);
// 确保至少有一个数字,固定值1
//requiredChars.Append('1');
// 确保至少有一个数字,随机值
requiredChars.Append(Numbers[random.Next(Numbers.Length)]);
}
if (useSpecialChars)
{
charPool.Append(SpecialCharacters);
// 确保至少有一个特殊字符,固定值!
//requiredChars.Append('!');
// 确保至少有一个特殊字符,随机值
requiredChars.Append(SpecialCharacters[random.Next(SpecialCharacters.Length)]);
}
if (charPool.Length == 0)
throw new ArgumentException("至少需要选择一种字符类型。");
if (requiredChars.Length > length)
throw new ArgumentException("所需的字符类型数量超过了指定的字符串长度。");
// 构建确保包含所有必要字符的初始部分
var result = new StringBuilder();
foreach (char c in requiredChars.ToString())
{
int index = charPool.ToString().IndexOf(c);
if (index != -1)
{
result.Append(charPool[index]);
charPool = charPool.Remove(index, 1); // 移除已使用的字符以避免重复
}
}
// 填充剩余的字符
for (int i = requiredChars.Length; i < length; i++)
{
int index = random.Next(0, charPool.Length);
result.Append(charPool[index]);
}
// 将结果打乱顺序,确保随机性
var shuffledResult = random.Shuffle(result.ToString());
return shuffledResult;
}
/// <summary>
/// 打乱字符串中的字符顺序。
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="input">要打乱的字符串。</param>
/// <returns>打乱后的字符串。</returns>
public static string Shuffle(this Random random, string input)
{
char[] array = input.ToCharArray();
for (int i = array.Length - 1; i > 0; i--)
{
int j = random.Next(i + 1);
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return new string(array);
}
}
扩展方法:打乱字符串中的字符顺序,也比较实用哦!
调用:
static void Main(string[] args)
{
Random random = new Random();
for (int i = 0; i < 115; i++)
{
var str = random.GenerateRandomString(useSpecialChars:true);
Console.WriteLine($"{str}");
}
Console.ReadKey();
}
运行结果:
sB9:JtsF-8
M<(:gcW\a3
u>QL&9q3DI
h;#Vmz}aP3
wXbu2L&1B}
2R)[ouG?*q
U)$`28mX3<
LW)}U/t6z`
^P1Q7tl"KZ
4p,@=Y|EV\
=Z%;3mNB\X
]BxY3S.F$r
$-'B~8E;sb
0$V~%N<w;L
eqngCI0Pv.
5. 生成不重复的随机数
1. 基础用法
public static class RandomExt
{
public static int NextUnique(this Random random,Hashtable hashtable,int maxValue)
{
if (hashtable == null) throw new ArgumentException("hashtable 不可为空。");
int num = random.Next(maxValue);
//不重复,则添加进Hashtable 并返回
if (!hashtable.ContainsValue(num))
{
hashtable.Add(num,num);
return num;
}
//重复,则继续调用自身生成不重复的随机数
return NextUnique(random,hashtable,maxValue);
}
}
调用:
static void Main(string[] args)
{
Hashtable hashtable = new Hashtable();
Random random = new Random();
for (int i = 0; hashtable.Count < 20; i++)
{
int num = random.NextUnique(hashtable,20);
Console.WriteLine($"{num}");
}
}
2. 进阶用法
基于第四小节的方法,新增一个GenerateRandomStringUnique
方法负责保存和检查唯一性。
public static class RandomExtension
{
/// <summary>
/// 生成一个随机字符串。
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="length">生成的字符串长度。</param>
/// <param name="useUppercase">是否包含大写字母。</param>
/// <param name="useLowercase">是否包含小写字母。</param>
/// <param name="useDigits">是否包含数字。</param>
/// <param name="useSpecialChars">是否包含特殊字符。</param>
/// <returns>生成的随机字符串。</returns>
/// <summary>
/// 生成一个随机字符串。
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="length">生成的字符串长度。</param>
/// <param name="useUppercase">是否包含大写字母。</param>
/// <param name="useLowercase">是否包含小写字母。</param>
/// <param name="useDigits">是否包含数字。</param>
/// <param name="useSpecialChars">是否包含特殊字符。</param>
/// <returns>生成的随机字符串。</returns>
public static string GenerateRandomString(this Random random, int length = 10, bool useUppercase = true, bool useLowercase = true, bool useDigits = true, bool useSpecialChars = false)
{
string CapitalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string LowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
string Numbers = "0123456789";
string SpecialCharacters = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
if (length <= 0)
throw new ArgumentException("长度必须大于零。", nameof(length));
// 定义字符集合
var charPool = new StringBuilder();
var requiredChars = new StringBuilder();
if (useUppercase)
{
charPool.Append(CapitalLetters);
// 确保至少有一个大写字母,固定值A
//requiredChars.Append('A');
// 确保至少有一个大写字母,随机值
requiredChars.Append(CapitalLetters[random.Next(CapitalLetters.Length)]);
}
if (useLowercase)
{
charPool.Append(LowercaseLetters);
// 确保至少有一个小写字母,固定值a
//requiredChars.Append('a');
// 确保至少有一个小写字母,随机值
requiredChars.Append(LowercaseLetters[random.Next(LowercaseLetters.Length)]);
}
if (useDigits)
{
charPool.Append(Numbers);
// 确保至少有一个数字,固定值1
//requiredChars.Append('1');
// 确保至少有一个数字,随机值
requiredChars.Append(Numbers[random.Next(Numbers.Length)]);
}
if (useSpecialChars)
{
charPool.Append(SpecialCharacters);
// 确保至少有一个特殊字符,固定值!
//requiredChars.Append('!');
// 确保至少有一个特殊字符,随机值
requiredChars.Append(SpecialCharacters[random.Next(SpecialCharacters.Length)]);
}
if (charPool.Length == 0)
throw new ArgumentException("至少需要选择一种字符类型。");
if (requiredChars.Length > length)
throw new ArgumentException("所需的字符类型数量超过了指定的字符串长度。");
// 构建确保包含所有必要字符的初始部分
var result = new StringBuilder();
foreach (char c in requiredChars.ToString())
{
int index = charPool.ToString().IndexOf(c);
if (index != -1)
{
result.Append(charPool[index]);
charPool = charPool.Remove(index, 1); // 移除已使用的字符以避免重复
}
}
// 填充剩余的字符
for (int i = requiredChars.Length; i < length; i++)
{
int index = random.Next(0, charPool.Length);
result.Append(charPool[index]);
}
// 将结果打乱顺序,确保随机性
var shuffledResult = random.Shuffle(result.ToString());
return shuffledResult;
}
/// <summary>
/// 打乱字符串中的字符顺序。
/// </summary>
/// <param name="random">Random 实例</param>
/// <param name="input">要打乱的字符串。</param>
/// <returns>打乱后的字符串。</returns>
public static string Shuffle(this Random random, string input)
{
char[] array = input.ToCharArray();
for (int i = array.Length - 1; i > 0; i--)
{
int j = random.Next(i + 1);
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return new string(array);
}
public static string GenerateRandomStringUnique(this Random random, Hashtable hashtable, int length = 10, bool useUppercase = true, bool useLowercase = true, bool useDigits = true, bool useSpecialChars = false)
{
if (hashtable == null) throw new ArgumentException("hashtable 不可为空。");
string str = random.GenerateRandomString(length, useUppercase, useLowercase, useDigits, useSpecialChars);
if (!hashtable.ContainsValue(str))
{
hashtable.Add(str, str);
return str;
}
return GenerateRandomStringUnique(random, hashtable, length, useUppercase, useLowercase, useDigits, useSpecialChars);
}
}
调用
static void Main(string[] args)
{
Hashtable hashtable = new Hashtable();
Random random = new Random();
// 只生成 1 个长度的只包含数字的 随机数的时候,只可能生成9个值,超过会报错
// 只生成 2 个长度的只包含数字的 随机数的时候,只可能生成10~99之间的值,总共89个值,超过会报错
for (int i = 0; hashtable.Count < 89; i++)
{
string result = random.GenerateRandomStringUnique(hashtable,2,false,false,true,false);
Console.WriteLine($"{result}");
}
}
正常调用,生成长度10的包含大小写字母,包含数字,不含特殊字符的随机数
static void Main(string[] args)
{
Hashtable hashtable = new Hashtable();
Random random = new Random();
for (int i = 0; hashtable.Count < 15; i++)
{
string result = random.GenerateRandomStringUnique(hashtable);
Console.WriteLine($"{result}");
}
}
运行结果:
lf41aCkdME
jFyHlT1UAr
Ni4y2JjAiQ
XJWbG2wK9e
Rn7j5bhFTO
hl7IWQ2LGC
016VCkgYzJ
D1KIgJeMQt
9TQJ5U4xTR
VcCVXJU76N
5wKRz1JrXI
RpJEn9MWhz
PiUQK4Xm7C
JfqK5pIadf
08Xy5SrQpp
结语
回到目录页: C# 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料:
.NET文档 - Random 类
C# Random类详解:生成随机数的实用指南
总结全网C#取随机数方法(整型,浮点型,字符串)
C# Random 随机数
C#产生指定范围随机数(整数、小数、字符、布尔,相对不重复的和唯一的)的几种方法