给出一个最快的求素数的算法

12 2025-09-01 10:22

要找到“最快”的求素数算法,我们得先明确几个关键点:
  • 范围:是求某个区间内的所有素数,还是判断单个超大数是否为素数?
  • 时间复杂度:是理论最优,还是实际最快?
  • 实现复杂度:是否允许使用复杂的数学理论或高性能计算资源?

最快求区间素数的算法:分段筛(Segmented Sieve)

如果你是要生成一个大区间内的所有素数(比如 1 到 10^12),那么:
分段筛(Segmented Sieve) 是实际中最快、内存可控的算法。

✅ 原理:

  1. 先用普通筛法(如埃氏筛)预处理出 [2, √n] 内的所有素数。
  2. 将目标区间 [L, R] 分成若干段,每段长度约为 √R
  3. 对每一段,用预处理的素数去标记非素数。
  4. 剩下的就是素数。

✅ 时间复杂度:

  • 预处理:O(√R log log √R)
  • 每段筛:O((R - L + 1) log log R)
  • 总体接近线性,且内存可控。

✅ 示例代码(Python):

Python
 
复制
import math

def simple_sieve(limit):
    is_prime = [True] * (limit + 1)
    is_prime[0:2] = [False, False]
    for i in range(2, int(math.isqrt(limit)) + 1):
        if is_prime[i]:
            for j in range(i*i, limit+1, i):
                is_prime[j] = False
    return [i for i, val in enumerate(is_prime) if val]

def segmented_sieve(L, R):
    limit = int(math.isqrt(R)) + 1
    base_primes = simple_sieve(limit)
    is_prime = [True] * (R - L + 1)
    
    for p in base_primes:
        start = max(p*p, ((L + p - 1) // p) * p)
        for j in range(start, R+1, p):
            is_prime[j - L] = False
    
    if L == 1:
        is_prime[0] = False
    return [L + i for i, val in enumerate(is_prime) if val]

# 示例:求1e6到1e6+100000内的素数
print(segmented_sieve(10**6, 10**6 + 100000)[:10])
 

判断单个超大数是否为素数:Miller-Rabin 素性测试

如果你是要判断一个超大数(比如几百位)是否为素数,那么:
Miller-Rabin 素性测试 是目前实际中最快的概率性算法。

✅ 特点:

  • 时间复杂度:O(k log³ n)k 是测试轮数。
  • 可通过选择足够大的 k(如 12 轮)使误判率极低(< 2^-64)。
  • 对于 64 位整数,确定性版本也可行(只需测试特定基)。

✅ 示例代码(Python,64位以内确定性):

Python
 
复制
def is_prime(n):
    if n < 2:
        return False
    for p in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]:
        if n % p == 0:
            return n == p
    d, s = n - 1, 0
    while d % 2 == 0:
        d //= 2
        s += 1
    for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
        if a >= n:
            continue
        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(s - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
    return True

# 示例
print(is_prime(982451653))  # True
 

✅ 总结:你该用哪个?

表格
 
复制
需求 推荐算法 时间复杂度 备注
求区间素数(如 1~N) 分段筛 接近线性 实际最快
判断单个超大数 Miller-Rabin O(log³ n) 实际最快
理论最优(但不可实现) AKS 素性测试 O(log⁶ n) 纯理论

全部评论

·