1020 字
5 分钟
Python 自定义函数之判断数字是否为素数

最近在学习 Python 编程的过程中,发现了许多关于判断数字是否为素数的自定义函数实现,其中不少资料的代码是错误的。素数是大于 1 的自然数,且只能被 1 和它本身整除。简单的素数,如 2 和 3,常常会在错误的代码中被漏掉。

今天,我们来探讨如何正确并且高效地实现一个判断素数的 Python 函数。

错误的实现#

很多教程或者网上的资料给出的判断素数的函数是这样的:

def isprime(x):
if x == 1:
return False
for i in range(2, int(sqrt(x)) + 1):
if x % i == 0:
return False
return True

乍一看,这段代码是可以工作的,但它有一个显著的问题:它没有正确处理素数 2 和 3。对于这两个数字,虽然它们是素数,但因为 for 循环从 2 开始判断,2 和 3 的特殊性会导致它们没有得到正确的判断。具体来说,range(2, int(sqrt(2)) + 1) 这样的循环范围对 2 和 3 并没有提供有效的判断。

错误的原因#

  • 素数 2 和 3:对于 x = 2x = 3 的情况,for 循环不会被执行,因为 sqrt(2)sqrt(3) 都小于 2。这样,这两个数字就可能在没有特别处理的情况下被错误地判断为非素数。

优化后的实现#

为了更好地处理素数 2 和 3,并提高算法效率,我们可以进一步优化这个函数:

  1. 排除偶数:除了 2 之外,所有偶数都不是素数。我们可以在判断时直接排除它们。
  2. 优化循环范围:我们可以通过只检查 6k ± 1 的形式来减少不必要的检查,从而提高效率。
  3. 特别处理 2 和 3:显式地处理 2 和 3,避免进入循环。

优化后的代码如下:

import math
def isprime(x):
if x <= 1:
return False
elif x <= 3:
return True
# 排除偶数和3的倍数
if x % 2 == 0 or x % 3 == 0:
return False
# 只检查形如6k±1的数
limit = int(math.sqrt(x)) + 1
for i in range(5, limit, 6): # 只检查6k±1
if x % i == 0 or x % (i + 2) == 0:
return False
return True

优化点解析:#

  1. 排除偶数和 3 的倍数:在循环前直接判断 x % 2 == 0x % 3 == 0,这样避免了大部分无用的判断,尤其是对于较大的数字。
  2. 检查 6k ± 1 的数:对于大于 3 的数字,我们可以通过检查 6k ± 1 的数来减少计算量。因为除了 2 和 3 之外,所有的素数都可以写成 6k ± 1 的形式(例如 5 = 61 - 1,7 = 61 + 1,11 = 62 - 1,13 = 62 + 1)。这样可以减少检查的数字,从而提高效率。
  3. 减少循环次数:通过直接计算 sqrt(x),并将循环范围限制在 sqrt(x) 以内,进一步提升了算法效率。

为什么这样改进更好?#

  1. 更高效:通过排除偶数和 3 的倍数,算法避免了大量无意义的计算。通过 6k ± 1 优化,进一步减少了检查的数字。
  2. 更准确:对 2 和 3 进行了特殊处理,确保它们不会被误判为非素数。
  3. 代码更加清晰易懂:这种实现方式直接而高效,同时也减少了不必要的复杂度。

总结#

在编程的过程中,常常会遇到一些常见的错误或者误解,比如判断素数时漏掉了 2 和 3。通过简单的优化,我们不仅能确保正确性,还能提高代码的运行效率。这个优化版的判断素数函数提供了更快的运行速度,尤其在处理大数字时,效率大大提高。

如果你在学习 Python 或者其他编程语言时遇到类似的问题,记得多思考、多验证。希望今天的分享对你有所帮助!

Python 自定义函数之判断数字是否为素数
https://sw.rscclub.website/posts/pythonsushu/
作者
杨月昌
发布于
2018-12-16
许可协议
CC BY-NC-SA 4.0