C#產生指定范圍隨機數(整數、小數、字符、布爾,相對不重復的和唯一的)的幾種方法
在開發過程中,常常要產生隨機數,如生成靜態 html 網頁時,文件名通常用產生隨機數的方式獲得,生成定單的時候,定單號也可以用產生隨機數的方式獲得等。
在 C# 中,一般都用 Random 產生隨機數,它可任意指定產生隨機數范圍。Random 結合數組,可以產生一些特殊范圍的隨機數,以滿足特殊的需要。如果在循環中產生隨機數,由于間隔時間短,每次產生的隨機數都一樣,需要先生成種子(有 3 種方法),再用該種子產生隨機數,或者鎖住 Random 對象,這樣才能減少產生隨機數的重復率。如果要產生唯一的隨機數(有 4 種方法),需要用數組或檢查已產生隨機數是否重復的辦法。
一、用 Random 產生指定范圍隨機數(整數隨機數)
1、產生指定上限的隨機數(如產生100以內的隨機數)
Random ran = new Random();
int n = ran.Next(100);
2、產生指定上下限的隨機數(如產生100到1000的隨機數)
Random ran = new Random();
int n = ran.Next(100, 1000);
二、用 Random 結合數組產生指定范圍隨機數(字符和布爾隨機數)
在某些情況下,隨機數只能取一些特殊指定的值,如不連續的數字或指定的一些單詞等,此時僅用 Random 無法達到要求,必須借住數組才能實現。實現思路大概是這樣:先把這些特殊的值存到數組中,然后把數組的長度作為 Random 的上限產生隨機數,此隨機數正是數組的下標,根據該下標取得數組的值。
(一)產生字符隨機數
1、產生不連續或指定值的隨機數
代碼如下:
public string GetRandom(string[] arr)
{
Random ran = new Random();
int n = ran.Next(arr.Length - 1);
return arr[n];
}
調用方法:
string[] arr = { "25", "28", "30", "50", "60" };
GetRandom(arr);
2、生成保留指定小數位數(例如 2 位)的隨機數
假如要用指定單詞作為隨機數的取值,代碼實現跟上例相同,所不同的僅是隨機數的取值,所以只要定義一個單詞數組直接調用上面代碼即可。
調用方法:
string[] arr = { "red", "green", "blue", "orange", "white" };
GetRandom(arr);
(二)產生布爾隨機數
public bool GenerateBoolRandom()
{
bool[] arr = { true, false };
Random ran = new Random();
return arr[ran.Next(2)];
}
調用方法:
Response.Write(GenerateBoolRandom());// 結果 true
三、用 Random 產生小數隨機數
在默認情況下,C# 只能產生任意小數隨機數,如果要產生指定范圍小數隨機數,需要自己寫代碼。寫代碼時,既可以把它們封裝到一個方法中又可以封裝到一個類中,后者可重載 C# 的 NextDouble() 方法。
1、把代碼封裝到一個方法
A、生成小數隨機數
public double NextDouble(Random ran, double minValue, double maxValue)
{
return ran.NextDouble() * (maxValue - minValue) + minValue;
}
調用:
Random ran = new Random();
double randNum = NextDouble(ran, 1.52, 2.65);
Response.Write(randNum);// 結果 2.30927768119112
B、生成保留指定小數位數(例如 2 位)的隨機數
public double NextDouble(Random ran, double minValue, double maxValue, int decimalPlace)
{
double randNum = ran.NextDouble() * (maxValue - minValue) + minValue;
return Convert.ToDouble(randNum.ToString("f" + decimalPlace));
}
調用:
Random ran = new Random();
double randNum = NextDouble(ran, 5.16, 8.68, 2);// 保留兩位小數
Response.Write(randNum);// 結果 8.46
2、把代碼封裝到一個類
代碼:
using System;
using System.Text;
public static class RandomDoubleRange
{
public static double NextDouble(this Random ran, double minValue, double maxValue)
{
return ran.NextDouble() * (maxValue - minValue) + minValue;
}
public static double NextDouble(this Random ran, double minValue, double maxValue, int decimalPlace)
{
double randNum = ran.NextDouble() * (maxValue - minValue) + minValue;
return Convert.ToDouble(randNum.ToString("f" + decimalPlace));
}
}
調用:
Random ran = new Random();
double randNum1 = ran.NextDouble(5.16, 8.68);
double randNum2 = ran.NextDouble(5.16, 8.68, 2);//保留兩位小數
Response.Write(randNum1 + "; " + randNum2);//結果 7.41055195257559; 6.69
四、產生相對不重復的隨機數
當在一個循環中生成隨機數,由于生成隨機數的時間間隔比較短,容易產生重復的隨機數,如果要產生不重復的隨機數,需要用種子或把隨機數對象鎖住,以下是它們的實現方法。
1、用種子產生相對不重復的隨機數
生成種子方法一:
public static int GenerateRandomSeed()
{
return (int)DateTime.Now.Ticks;
}
產生 1 到 10 的隨機數為:2, 5, 2, 5, 7, 3, 4, 4, 6, 3
生成種子方法二:
using System.Text.RegularExpressions;
public static int GenerateRandomSeed()
{
return Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
}
產生 1 到 10 的隨機數為:1, 7, 4, 9, 8, 1, 8, 7, 9, 8
生成種子方法三:
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);
}
產生 1 到 10 的隨機數為:4, 8, 7, 2, 6, 7, 6, 5, 5, 7
產生指定數目的隨機數并存到數組:
// randNum 為產生隨機數的數目
public int[] GenerateRandom(int minValue, int maxValue, int randNum)
{
Random ran = new Random(GenerateRandomSeed());
int[] arr = new int[randNum];
for (int i = 0; i < randNum; i++)
{
arr[i] = ran.Next(minValue, maxValue);
}
return arr;
}
調用方法:
int[] arr = GenerateRandom(1, 10, 10);
string temp = string.Empty;
for (int i = 0; i < arr.Length; i++)
{
temp += arr[i].ToString() + ", ";
}
Response.Write(temp);
2、通過鎖住 Random 對象產生相對不重復的隨機數
產生隨機數:
public int GenerateRandom(Random ran, int minValue, int maxValue)
{
lock (ran) // 鎖住 Random 對象
{
return ran.Next(minValue, maxValue);
}
}
調用:
int[] arr = new int[5];
Random ran = new Random();
for (int i = 0; i < 5; i++)
{
arr[i] = GenerateRandom(ran, 1, 10);// 結果 5, 7, 2, 5, 2
}
五、生成絕對不重復的指定范圍的隨機數
1、方法一:先生成一個索引數組,再把產生的隨機數作為索引從該數組中取一個數作為隨機數。
生成隨機數:
// n 為生成隨機數個數
public int[] GenerateUniqueRandom(int minValue, int maxValue, int n)
{
//如果生成隨機數個數大于指定范圍的數字總數,則最多只生成該范圍內數字總數個隨機數
if (n > maxValue - minValue + 1)
n = maxValue - minValue + 1;
int maxIndex = maxValue - minValue + 2;// 索引數組上限
int[] indexArr = new int[maxIndex];
for (int i = 0; i < maxIndex; i++)
{
indexArr[i] = minValue - 1;
minValue++;
}
Random ran = new Random();
int[] randNum = new int[n];
int index;
for (int j = 0; j < n; j++)
{
index = ran.Next(1, maxIndex - 1);// 生成一個隨機數作為索引
//根據索引從索引數組中取一個數保存到隨機數數組
randNum[j] = indexArr[index];
// 用索引數組中最后一個數取代已被選作隨機數的數
indexArr[index] = indexArr[maxIndex - 1];
maxIndex--; //索引上限減 1
}
return randNum;
}
調用方法:
GenerateUniqueRandom(1, 10, 10);// 結果 9, 5, 10, 1, 7, 3, 2, 4, 6, 8
GenerateUniqueRandom(1, 10, 5);// 結果 3, 7, 6, 1, 9
2、方法二:用 do...while 循環來生成不重復的隨機數,用 for 循環來檢查產生的隨機數是否重復,只有不重復的隨機數才保存到數組。
生成隨機數:
// n 生成隨機數個數
public int[] GenerateUniqueRandom(int minValue, int maxValue, int n)
{
// Random.Nex(1, 10) 只能產生到 9 的隨機數,若要產生到 10 的隨機數, maxValue 要加 1
maxValue++;
// Random.Nex(1, 10) 只能產生 9 個隨機數,因此 n 不能大于 10 - 1
if (n > maxValue - minValue)
n = maxValue - minValue;
int[] arr = new int[n];
Random ran = new Random((int)DateTime.Now.Ticks);
bool flag = true;
for (int i = 0; i < n; i++)
{
do
{
int val = ran.Next(minValue, maxValue);
if (!IsDuplicates(ref arr, val))
{
arr[i] = val;
flag = false;
}
} while (flag);
if (!flag)
flag = true;
}
return arr;
}
// 查檢當前生成的隨機數是否重復
public bool IsDuplicates(ref int[] arr, int currRandNum)
{
bool flag = false;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == currRandNum)
{
flag = true;
break;
}
}
return flag;
}
調用方法:
int[] arr = GenerateUniqueRandom(1, 10, 10);// 生成 10 個 1 到 10 的隨機數
for (int i = 0; i < arr.Length; i++)
Response.Write(arr[i] + ", ");// 結果 10, 7, 9, 4, 3, 5, 1, 2, 6, 8
GenerateUniqueRandom(1, 10, 5);// 生成 5 個 1 到 10 的隨機數,結果 9, 1, 7, 2, 10
3、方法三:用 do...while 循環來檢查產生的隨機數是否重復,只有不重復的隨機數才保存到哈希表。
生成隨機數:
using System.Collections;
// n 為生成隨機數個數
public Hashtable GenerateUniqueRandom(int minValue, int maxValue, int n)
{
// Random.Next(1, 10) 只能產生到 9 的隨機數,若要產生到 10 的隨機數,maxValue 要加 1
maxValue++;
// Random.Next(1, 10) 只能產生 9 個隨機數,因此 n 不能大于 10 - 1
if (n > maxValue - minValue)
n = maxValue - minValue;
Hashtable ht = new Hashtable();
Random ran = new Random((int)DateTime.Now.Ticks);
bool flag = true;
for (int i = 0; i < n; i++)
{
do
{
int val = ran.Next(minValue, maxValue);
if (!ht.ContainsValue(val))
{
ht.Add(i, val);
flag = false;
}
} while (flag);
if (!flag)
flag = true;
}
return ht;
}
調用方法:
Hashtable ht = GenerateUniqueRandom(1, 10, 10);// 生成 10 個 1 到 10 的隨機數
foreach (DictionaryEntry de in ht)
Response.Write(de.Value.ToString() + ", ");// 結果 10, 7, 9, 4, 3, 5, 1, 2, 6, 8
GenerateUniqueRandom(1, 10, 5);// 生成 5 個 1 到 10 的隨機數,結果 4, 10, 9, 7, 6
4、方法四:用 Linq 生成不重復的隨機數
生成隨機數:
using System.Linq;
public IEnumerable<int>
GenerateNoDuplicateRandom(int minValue, int maxValue)
{
return Enumerable.Range(minValue, maxValue).OrderBy(g => Guid.NewGuid());
}
調用方法:
IEnumerable<int> list = GenerateNoDuplicateRandom(1, 10);
string str = string.Empty;
foreach (int item in list)
{
str += item.ToString() + ", ";
}
Response.Write(str);// 結果 5, 2, 10, 1, 7, 6, 8, 3, 9, 4
以上幾種產生指定隨機數的方法,都通過測試,可根據實際開發需要靈活選擇,一般情況都是直接用 Random 就可以了。