质数查找函数优化求助:已优化平方根计算,求进一步提效方案
嘿,很高兴看到你已经迈出了优化的第一步——把Math.Sqrt(N)移出循环,这确实能减少不少重复计算!针对你的质数查找函数,我还有几个实用的优化方向,从时间和内存效率两方面帮你提升:
一、用埃拉托斯特尼筛法(Sieve of Eratosthenes)替代逐个判断
你现在的思路是生成奇数再逐个调用isSimple验证,这种“逐个检查”的方式在处理大数值范围时效率很低。筛法则是通过批量标记非质数的方式一次性找出范围内所有质数,时间复杂度能降到O(n log log n),比逐个判断高效得多。
而且我们可以优化筛法,只处理奇数(除了2以外,所有偶数都不是质数),这样能直接砍掉一半的内存占用和计算量。比如用BitArray替代普通布尔数组——.NET里普通bool占1字节,而BitArray每个元素只占1位,内存占用直接降到原来的1/8,对大数值范围来说内存压力会小很多。
给你个示例代码参考:
public static List<int> GetPrimes(int max) { if (max < 2) return new List<int>(); // BitArray索引i对应数字2i+1(只存储奇数) BitArray isPrime = new BitArray((max + 1) / 2, true); List<int> primes = new List<int> { 2 }; // 先加入唯一的偶质数 for (int i = 1; i < isPrime.Count; i++) { if (isPrime[i]) { int currentPrime = 2 * i + 1; primes.Add(currentPrime); // 从currentPrime的平方开始标记倍数(更小的倍数已经被之前的质数标记过) if ((long)currentPrime * currentPrime > max) continue; // 步长取2*currentPrime,跳过偶数倍数 for (int j = 2 * i * i + 2 * i; j < isPrime.Count; j += currentPrime) { isPrime[j] = false; } } } return primes; }
二、优化单个质数判断的
isSimple方法 如果你的场景是偶尔需要判断单个数字是否为质数,而非批量查找,那可以进一步优化isSimple的逻辑:
- 先快速排除小于2的数、偶数(除了2)
- 预存一批小质数(比如100以内的质数),先检查这些小质数是否能整除目标数——大部分合数都能被小质数整除,这能减少很多不必要的循环
- 只检查奇数因子,从3开始步长为2遍历到sqrt(n)
示例代码:
// 预存小质数,减少重复计算 private static readonly int[] SmallPrimes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; public static bool IsSimple(int n) { if (n < 2) return false; if (n == 2) return true; if (n % 2 == 0) return false; // 排除所有偶合数 // 先检查小质数 foreach (int p in SmallPrimes) { if ((long)p * p > n) return true; if (n % p == 0) return false; } // 从31开始,只检查奇数因子 for (int i = 31; (long)i * i <= n; i += 2) { if (n % i == 0) return false; } return true; }
三、超大数据范围的内存优化:分段筛法
如果需要处理的数值范围大到连BitArray都装不下(比如查找1亿以上的质数),可以用分段筛法:把整个范围分成若干小段,每次只加载一段到内存处理,处理完就释放该段内存,再处理下一段。这种方法能把内存占用控制在很小的范围内,适合超大规模的质数查找。
内容的提问来源于stack exchange,提问作者user9534998
相关产品推荐
相关产品推荐

