范围内获取不重复的随机数

C#范围内生成不重复随机数 范围为 [startNum, endNum] , 其中0<=startNum<endNum 。 生成的个数为needNum,并且needNum <= endNum - startNum + 1 因为C#的Random类不进行种子设置的话是伪随机,所以我们要改进一下Random类的Next方法,让它尽可能朝着真随机靠近。 优化后的代码如下: public static int Random(int starNum, int endNum) { byte [] randomBytes = new byte[4]; RNGCryptoServiceProvider rngProvider = new RNGCryptoServiceProvider(); rngProvider.GetBytes(randomBytes); Int32 iSeed = BitConverter.ToInt32(randomBytes, 0); Random random = new Random(iSeed); return random.Next(starNum, endNum + 1); } public static bool IsParameterValid(int startNum, int endNum, int needCount) { if (startNum < 0 || endNum <0 || startNum > endNum || needCount == 0 || needCount > endNum - startNum + 1) { return false; } return true; } 方法一 使用两个数组,从第一个数组中随机位置抽取一个,放到第二个数组中,并且在第一个数组中删除这个值, 接下来从第一个数组的剩余数据中重复上面的步骤,直到第二个数组中获得了目标个数的值停止。 代码如下: public static List<int> PickMethod1(int startNum, int endNum, int needCount) { if (!IsParameterValid(startNum, endNum, needCount)) { return null; } List<int> posList = new List<int>(); List<int> newPosList = new List<int>(); for (int i = 0; i <= endNum - startNum; i++) { posList.Add(i); } int count = 0; while (count < needCount) { int pickPos = Random(0, posList.Count -1); newPosList.Add(posList[pickPos]); posList.RemoveAt(pickPos); count++; } return newPosList; } 优点:从剩余的数据中随机取值,不用判断重复,相对于方法二来说速度会更快,特别是needNum 很接近 endNum - startNum + 1的时候,会更加明显 缺点:需要一个额外的数组,需要更多的内存 方法二 使用HashTable,在一个循环中不停地在范围内随机的取值,并且检查检查这个值是否在HashTable中,如果不存在则存放到Hashtable中, 如果存在则重复前面的步骤,直到Hashtable的Count数量达到想要的数量值。 代码如下: ...

April 16, 2022 · 2 min · 240 words · Link