Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

素数与筛法

| , 2 minutes reading.

素数与筛法:逻辑的原子

算法背后的故事:希腊人的过滤器

公元前 200 年,亚历山大图书馆的馆长 埃拉托斯特尼 (Eratosthenes) 对素数着了迷——那些没有“朋友”(除了 1 和自己以外没有因数)的数字。

他意识到,寻找素数就像在河里淘金。你不需要拿起每一块石头看它是不是金子,你需要建一个 筛子 (Sieve)

想象一张从 2 到 100 的数字网格。

  1. 从 2 开始。它是素数。现在,伸手“划掉”网格中所有 2 的倍数(4, 6, 8…)。它们绝对不是素数。
  2. 移动到 3。它是素数。划掉所有 3 的倍数(6, 9, 12…)。
  3. 跳过 4(它已经被划掉了)。
  4. 移动到 5…

当你完成时,剩下的只有纯净的“黄金”。这就是 埃拉托斯特尼筛法。直到今天,它依然是寻找小规模素数最有效的方法之一。

为什么需要它?

  • 密码学: RSA 加密基于分解两个巨大素数乘积的难度。寻找这些素数是构建安全互联网的第一步。
  • 哈希: 哈希表的大小通常取素数,因为这能最大限度地减少模运算中的“碰撞”。
  • 游戏机制: 在遊戲中使用素数作为刷新率或周期性事件,以防止它们过于频繁地同步(重叠)。

算法是如何“思考”的

筛法是一个消除引擎

  1. 素数假设: 我们开始时假设每个数字都是素数(一个全是 True 的布尔数组)。
  2. 划线: 从 2 开始,如果一个数字仍为 True,我们就遍历它的倍数并设为 False
  3. 优化 (平方规则): 你不需要从 2imesP2 imes P 开始划线,你可以从 PimesPP imes P 开始。因为比 P2P^2 小的倍数一定已经被更小的素数处理过了。
  4. 边界: 要找到 NN 以内的所有素数,你只需要处理到 N\sqrt{N} 即可。

工程决策:大素数问题

筛法在寻找 1000 万以内的所有素数时表现出色。但如果你需要一个 2048 位的单一素数用于 TLS 证书呢?

  • 筛法需要的内存将超过全宇宙的上限。
  • 此时,工程师会使用 概率性素性测试(如 Miller-Rabin)。这些测试不一定能 100% 证明一个数是素数,但它们能在几毫秒内以 99.9999999% 的确定性完成。在工程中,这种速度下的“足够好”就是标准。

实现参考 (Python)

def sieve_of_eratosthenes(n):
    # 1. 创建筛子,假设所有数都是素数
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False # 0 和 1 不是素数
    
    # 2. 遍历到 sqrt(n)
    p = 2
    while p * p <= n:
        if is_prime[p]:
            # 3. 从 p*p 开始划掉所有 p 的倍数
            for i in range(p * p, n + 1, p):
                is_prime[i] = False
        p += 1
    
    # 4. 收集幸存者
    return [i for i, prime in enumerate(is_prime) if prime]

# 示例
print(f"50 以内的素数: {sieve_of_eratosthenes(50)}")

小结

素数教会我们:复杂性是由简单构建的。通过滤除合数的杂音,我们抵达了数学的基础构件。它提醒我们,在安全和工程领域,最坚固的基石往往也是最基础的那些。