Python嵌套for循环实现埃氏筛求素数出现无限循环如何解决
问题诱因排查
你这段代码进入无限循环的直接原因是外层for i in primes循环遍历的是动态变化的列表:Python的for循环遍历列表时会按索引依次取元素,你在内层循环中只要判断j%i !=0就执行primes.append(j),会让primes列表持续变长,循环永远触达不到列表末尾,自然不会终止。
除此之外代码逻辑本身也完全不符合埃拉托斯特尼筛法的规则:
- 筛法核心是标记排除素数的倍数,你当前的判断逻辑是只要数不能被当前遍历到的素数整除就直接加入素数列表,会把大量合数、0、1甚至重复值错误加入列表
- 内层循环固定遍历
range(50),每次外层循环拿到一个新的i,都会重新从0到49扫一遍,完全没有筛法「标记后跳过重复判断」的效率优势
正确的嵌套循环筛法实现
筛法实现的核心是提前固定待筛选的数值范围,用标记数组记录合数,不要在遍历素数列表时动态修改列表本身:
# 目标:生成小于50的所有素数 max_num = 50 # 初始化标记数组,索引对应数字,值为True代表暂时判定为素数 is_prime = [True] * max_num # 0和1不是素数,直接标记 is_prime[0] = is_prime[1] = False # 外层遍历到根号max_num即可,更大的合数肯定已经被更小的因子标记过 for i in range(2, int(max_num ** 0.5) + 1): if is_prime[i]: # 内层循环标记i的所有倍数为合数,从i*i开始可以减少重复判断 for j in range(i * i, max_num, i): is_prime[j] = False # 收集所有标记为素数的数字 primes = [num for num, flag in enumerate(is_prime) if flag] print(primes)
运行后输出结果为:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47],符合预期。
注意:如果要写朴素遍历判断素数的逻辑,也不要在遍历素数列表的过程中往列表内追加元素,可以先遍历固定范围的候选数,对每个候选数判断是否能被已有素数整除,再决定是否加入素数列表,避免触发无限循环。
内容的提问来源于stack exchange,提问作者Fly by Night
相关产品推荐
相关产品推荐

