计算两百万以下质数和结果不符,如何修正得到正确值?
问题分析与修正方案
你的代码存在多处逻辑错误,导致漏掉了部分质数(尤其是√2000000以内的小质数),最终总和偏小。核心问题及修正方法如下:
原代码的错误点
- 小质数被遗漏:第二个循环中,当
c是primos列表中的质数时,会因为c == num5跳过整除判断,后续又通过c % num5 == 0的判断将其排除在primos2之外,导致2、3、5等小质数未被计入总和。 - 循环范围错误:第一个循环的范围
range(1, int(math.sqrt(num)))未包含int(math.sqrt(num)),若该数值为质数会被漏掉。 - 判断逻辑错误:第二个循环结束后,用
primos的最后一个元素num5判断c是否能被整除,这是错误的——如果循环提前break(找到能整除的因子),num5是那个因子;如果循环正常结束(无因子),num5是最后一个质数,此时用它判断会导致误判。 - 缺失模块导入:代码未导入
math模块,实际运行会报错。
修正后的代码(使用埃拉托斯特尼筛法,高效且正确)
埃氏筛法是筛选质数的经典高效算法,能避免原代码的逻辑漏洞:
def SumOfPrimesBelow(num): if num <= 2: return 0 # 初始化筛子,默认所有数都是质数(True表示是质数) sieve = [True] * num sieve[0] = sieve[1] = False # 0和1不是质数 for i in range(2, int(num ** 0.5) + 1): if sieve[i]: # 将i的所有倍数标记为非质数 sieve[i*i : num : i] = [False] * len(sieve[i*i : num : i]) # 计算所有质数的和 return sum(i for i, is_prime in enumerate(sieve) if is_prime) print(SumOfPrimesBelow(2000000)) # 输出142913828922
代码说明
- 筛子初始化:创建一个长度为
num的列表sieve,用True标记质数,False标记非质数。 - 标记非质数:从2开始遍历到√num,如果当前数是质数,就将其所有倍数标记为非质数。
- 求和:遍历筛子,将所有标记为
True的数(质数)相加。
这个方法不仅逻辑正确,运行效率也远高于原代码,能快速处理两百万以内的质数求和。
内容的提问来源于stack exchange,提问作者Bernardo Azeredo
相关产品推荐
相关产品推荐

