这年头,谁还不会点 Python 啊?但是,真要让你手撸一个找素数的函数,你确定你能写得又快又漂亮?别慌,咱今天就好好聊聊这事儿,用 Python 怎么把素数给揪出来。

最简单的,也是最容易想到的,就是直接暴力试除法。啥叫暴力?就是从 2 开始,一直除到这个数的平方根(取整),看看能不能被整除。如果都不能,那它就是素数

“`python
import math

def is_prime_brute_force(number):
“””
判断一个数是否为素数(暴力试除法)
“””
if number <= 1:
return False
for i in range(2, int(math.sqrt(number)) + 1):
if number % i == 0:
return False
return True

举个例子

print(is_prime_brute_force(17)) # True
print(is_prime_brute_force(20)) # False
“`

这段代码够直白吧?但是,说实话,效率真不高!尤其当你需要找一大堆素数的时候,那速度简直让人崩溃。想想,如果让你判断1000007是不是素数,它得试除到1000多,想想都觉得慢。

那有没有快一点的方法呢?当然有!

接下来要说的,是埃拉托斯特尼筛法。这个方法听起来高大上,其实原理很简单:

  1. 先把 2 到 n 的所有整数都列出来。
  2. 找到最小的素数 2,然后把 2 的所有倍数都划掉(因为它们肯定不是素数)。
  3. 找到下一个没有被划掉的数,它一定是素数。然后把它的所有倍数都划掉。
  4. 重复步骤 3,直到所有小于等于 n 的数的倍数都被划掉。

剩下的那些没被划掉的,就是素数啦!

这就像筛沙子一样,把不是素数的“沙子”都筛掉,剩下的就是金灿灿的“素数”了。

“`python
def eratosthenes_sieve(n):
“””
埃拉托斯特尼筛法求n以内的所有素数
“””
prime = [True] * (n + 1) # 创建一个布尔数组,初始都设为True
prime[0] = prime[1] = False # 0和1不是素数
p = 2
while (p * p <= n):
if (prime[p] == True):
# 如果p是素数,则将其倍数都标记为非素数
for i in range(p * p, n + 1, p):
prime[i] = False
p += 1

# 收集所有素数
primes = []
for p in range(2, n + 1):
    if prime[p]:
        primes.append(p)
return primes

试试看

primes = eratosthenes_sieve(50)
print(primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
“`

这段代码效率比暴力试除法高多了!特别是当 n 很大的时候,优势更明显。但是,它也有缺点:需要占用额外的空间来存储那个布尔数组。

如果你对空间复杂度比较敏感,或者 n 非常非常大,甚至超出了内存的限制,那该怎么办呢?那就需要用到一些更高级的算法了,比如线性筛(欧拉筛)。

线性筛的原理稍微复杂一点,但它的核心思想是:每个合数只会被它的最小质因子筛掉一次。这样,就可以保证每个数只会被处理一次,从而达到线性时间复杂度。

“`python
def linear_sieve(n):
“””
线性筛(欧拉筛)求n以内的所有素数
“””
primes = []
is_prime = [True] * (n + 1)
is_prime[0] = is_prime[1] = False
for i in range(2, n + 1):
if is_prime[i]:
primes.append(i)
for j in range(len(primes)):
if i * primes[j] > n:
break
is_prime[i * primes[j]] = False
if i % primes[j] == 0:
break
return primes

再试试看

primes = linear_sieve(50)
print(primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
“`

这段代码,虽然看起来比埃拉托斯特尼筛法复杂一些,但它的效率更高,空间复杂度也更优秀。这绝对是 Python素数的利器!

所以说,Python素数,方法真的很多。用哪种方法,取决于你的具体需求。如果只是判断一个数是不是素数,暴力试除法也够用。如果需要找一大堆素数,那就得考虑埃拉托斯特尼筛法或者线性筛了。记住,没有最好的算法,只有最合适的算法。

写代码嘛,就像谈恋爱,适合自己的才是最好的。

当然,除了上面这些,还有一些更高级的素数判定算法,比如 Miller-Rabin 素性测试。但那些算法比较复杂,一般情况下用不到。所以,掌握了上面这几种方法,就足够应付大部分场景了。

最后,再啰嗦一句:写代码,多思考,多实践,才能真正掌握!别光看不练,赶紧动手试试吧!说不定,你还能发现更牛的素数算法呢!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。