素数与筛法
Published: Thu Feb 19 2026 | Modified: Sat Feb 07 2026 , 2 minutes reading.
素数与筛法:逻辑的原子
算法背后的故事:希腊人的过滤器
公元前 200 年,亚历山大图书馆的馆长 埃拉托斯特尼 (Eratosthenes) 对素数着了迷——那些没有“朋友”(除了 1 和自己以外没有因数)的数字。
他意识到,寻找素数就像在河里淘金。你不需要拿起每一块石头看它是不是金子,你需要建一个 筛子 (Sieve)。
想象一张从 2 到 100 的数字网格。
- 从 2 开始。它是素数。现在,伸手“划掉”网格中所有 2 的倍数(4, 6, 8…)。它们绝对不是素数。
- 移动到 3。它是素数。划掉所有 3 的倍数(6, 9, 12…)。
- 跳过 4(它已经被划掉了)。
- 移动到 5…
当你完成时,剩下的只有纯净的“黄金”。这就是 埃拉托斯特尼筛法。直到今天,它依然是寻找小规模素数最有效的方法之一。
为什么需要它?
- 密码学: RSA 加密基于分解两个巨大素数乘积的难度。寻找这些素数是构建安全互联网的第一步。
- 哈希: 哈希表的大小通常取素数,因为这能最大限度地减少模运算中的“碰撞”。
- 游戏机制: 在遊戲中使用素数作为刷新率或周期性事件,以防止它们过于频繁地同步(重叠)。
算法是如何“思考”的
筛法是一个消除引擎。
- 素数假设: 我们开始时假设每个数字都是素数(一个全是
True的布尔数组)。 - 划线: 从 2 开始,如果一个数字仍为
True,我们就遍历它的倍数并设为False。 - 优化 (平方规则): 你不需要从 开始划线,你可以从 开始。因为比 小的倍数一定已经被更小的素数处理过了。
- 边界: 要找到 以内的所有素数,你只需要处理到 即可。
工程决策:大素数问题
筛法在寻找 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)}")小结
素数教会我们:复杂性是由简单构建的。通过滤除合数的杂音,我们抵达了数学的基础构件。它提醒我们,在安全和工程领域,最坚固的基石往往也是最基础的那些。
