使用丢弃策略的C#随机数生成器返回重复序列问题求助
问题分析与修复方案
嘿,我来帮你拆解下为什么你的随机数生成器只会返回相同数字——核心有两个关键问题:
1. 随机数生成函数的种子完全没保持状态
你的GenerateNextRandomNumber()函数每次调用时,都会重新用当前毫秒值初始化局部变量seed,而且这个seed是函数内的临时变量,调用完就消失了。
计算机的循环速度极快,短时间内多次调用这个函数时,DateTime.Now.Millisecond的值根本不会变化,所以每次计算出来的随机数完全一样。另外,就算毫秒变了,每次重新初始化种子也会破坏伪随机数的序列连续性,完全达不到“随机”的效果。
修正后的随机数生成函数
把seed改成类的成员变量,只初始化一次,每次生成新数时更新这个种子:
private long _seed; // 类级别的成员变量,用来保持随机数生成的状态 // 在类的构造函数里初始化种子(用Ticks比Millisecond精度更高) public YourRandomGeneratorClass() { _seed = DateTime.Now.Ticks; } public int GenerateNextRandomNumber() { int j = 24; int k = 55; long m = (long)Math.Pow(2, 32); // 使用类成员的_seed,而不是每次重新创建 long randomNumber = (j * _seed + k) % m; _seed = randomNumber; // 更新种子,供下次生成使用 int finalRandom = (int)randomNumber; return Math.Abs(finalRandom); }
2. 生成序列的逻辑完全不符合“丢弃策略”
你写的GenerateRandomwithdiscarding函数逻辑完全错误:
while(count<j)循环只是重复给sequence[j]赋值count次,最后sequence[j]只会保留最后一次生成的数值- 整个逻辑没有任何检查重复、丢弃重复值的逻辑,完全达不到你想要的“生成不重复随机序列”的效果
修正后的丢弃策略实现
用HashSet来快速记录已经生成过的数字,遇到重复就丢弃,直到收集到足够数量的不重复随机数:
public int[] GenerateRandomWithDiscarding(int n, int min, int max) { // 先做边界检查:如果要生成的个数超过取值范围的唯一值数量,直接抛出异常 if (n > (max - min + 1)) { throw new ArgumentException("要生成的随机数个数超过了取值范围的唯一值总数"); } int[] sequence = new int[n]; HashSet<int> usedNumbers = new HashSet<int>(); // 快速查重的集合 int currentIndex = 0; while (currentIndex < n) { int rawRandom = GenerateNextRandomNumber(); // 将原始随机数映射到[min, max]区间 int mappedRandom = min + rawRandom % (max - min + 1); // 如果这个数没出现过,就加入序列和已使用集合 if (!usedNumbers.Contains(mappedRandom)) { usedNumbers.Add(mappedRandom); sequence[currentIndex] = mappedRandom; currentIndex++; } // 如果重复了,直接跳过(丢弃),继续生成下一个 } return sequence; }
额外提示
如果你不需要自己实现伪随机数生成器,.NET自带的Random类已经足够好用,它内部已经处理了种子状态和序列生成的问题,你可以直接用它来简化代码——自己实现伪随机数很容易踩各种数学和状态管理的坑哦。
内容的提问来源于stack exchange,提问作者finsters
相关产品推荐
相关产品推荐

