如何提升自定义大素数检测函数的运行效率?
素数检测函数优化方案
原代码的核心问题
- 全局变量
primes滥用:全局状态会导致多次调用函数时逻辑混乱,每次检测大数都要从上次位置生成素数,冗余操作多;加上print(primes)的实时输出,严重拖慢运行速度。 - 素数生成逻辑冗余:为检测目标数,先生成所有小于等于其平方根的素数完全没必要——检测素数只需要用小于等于其平方根的数试除,不需要预先提取这些数里的素数。
is_divisible函数效率低下:遍历所有已存素数,未在除数超过目标数平方根时停止;且n == num的判断完全多余(除数最大到sqrt(num),不可能等于目标数)。
优化后的实现方案
方案1:优化试除法(无素数缓存,适合单次检测大数)
直接针对目标数做优化试除,逻辑简洁高效:
import math def is_prime(number): # 处理特殊情况 if number <= 1: return False if number == 2: return True # 偶数直接排除 if number % 2 == 0: return False # 只检查奇数除数,从3到number的整数平方根,步长2 sqrt_num = math.isqrt(number) # 避免浮点数误差,返回整数平方根更高效 for i in range(3, sqrt_num + 1, 2): if number % i == 0: return False return True
优化点说明:
- 用
math.isqrt替代math.ceil(math.sqrt),避免浮点数运算误差,同时提升效率。 - 先排除偶数,之后只遍历奇数除数,减少一半循环次数。
- 无需额外素数列表,直接试除到目标数的平方根即可。
方案2:带素数缓存的版本(适合多次检测,避免重复计算)
如果需要多次检测不同数字,用闭包保存素数缓存替代全局变量,同时优化生成逻辑:
import math def create_prime_checker(): primes = [2] def is_prime(number): if number <= 1: return False if number == 2: return True # 先检查是否能被已有的素数整除 sqrt_num = math.isqrt(number) for p in primes: if p > sqrt_num: break if number % p == 0: return False # 按需生成新素数到sqrt(number),补充进缓存 start = primes[-1] + 1 start = start if start % 2 != 0 else start + 1 # 确保从奇数开始 for i in range(start, sqrt_num + 1, 2): is_i_prime = True for p in primes: if p > math.isqrt(i): break if i % p == 0: is_i_prime = False break if is_i_prime: primes.append(i) # 同步检查目标数是否能被新素数整除,提前返回结果 if number % i == 0: return False return True return is_prime # 使用示例 prime_checker = create_prime_checker() print(prime_checker(1000003)) # 检测大素数 print(prime_checker(1000001)) # 检测合数
优化点说明:
- 用闭包保存素数缓存,避免全局变量的副作用。
- 检查目标数时,遍历已存素数超过平方根就停止,减少不必要计算。
- 生成新素数时,仅检查到该数的平方根,而非遍历所有已存素数。
- 生成新素数的同时直接检查目标数,提前返回结果。
原代码崩溃原因
原代码中全局变量primes会持续膨胀,加上每次循环都打印整个列表,检测较大数字时列表体积过大,占用内存过多,最终导致VS Code崩溃。去掉print(primes)并优化素数生成逻辑后,内存占用会大幅降低。
内容的提问来源于stack exchange,提问作者marnix mulder
相关产品推荐
相关产品推荐

