任何人都可以提供任何素数计数函数实现的计算上可行的伪代码吗?我最初尝试编写Hardy-Wright 算法,但它的阶乘开始产生严重的溢出,而且许多其他算法似乎必然会产生类似的问题。我在 Google 上搜索了实用的解决方案,但充其量只是发现了非常深奥的数学,我从未见过在传统程序中实现过这些数学。
2 回答
素数计数函数 pi(x) 计算不超过 x 的素数的数量,几个世纪以来一直让数学家着迷。18 世纪初,Adrien-Marie Legendre 给出了一个公式,它使用辅助函数 phi(x,a) 计算不大于 x 且未被第一个 a 素数筛选的数;例如,对于数字 1、7、11、13、17、19、23、29、31、37、41、43、47 和 49,phi(50,3) = 14。 phi 函数可以计算为 phi (x,a) = phi(x,a-1) - phi(x/P(a),a-1),其中 phi(x,1) 是不超过 x 和 P(a) 的奇数个数是第 a 个素数(从 P(1)=2 开始计数)。
function phi(x, a)
if (phi(x, a) is in cache)
return phi(x, a) from cache
if (a == 1)
return (x + 1) // 2
t := phi(x, a-1) - phi(x // p[a], a-1)
insert phi(x, a) = t in cache
return t
数组 p 存储小 a 的第 a 个素数,通过筛分计算得出。缓存很重要;没有它,运行时间将是指数级的。给定 phi,Legendre 的素数计数公式是 pi(x) = phi(x,a) + a - 1,其中 a = pi(floor(sqrt(x)))。勒让德使用他的公式计算 pi(10^6),但他报告了 78526 而不是正确答案 78498,即使是错误的,对于复杂的手动计算来说也非常接近。
在 1950 年代,Derrick H. Lehmer 给出了一种改进的素数计数算法:
function pi(x)
if (x < limit) return count(primes(x))
a := pi(root(x, 4)) # fourth root of x
b := pi(root(x, 2)) # square root of x
c := pi(root(x, 3)) # cube root of x
sum := phi(x,a) + (b+a-2) * (b-a+1) / 2
for i from a+1 to b
w := x / p[i]
lim := pi(sqrt(w))
sum := sum - pi(w)
if (i <= c)
for j from i to lim
sum := sum - pi(w / p[j]) + j - 1
return sum
例如,pi(10^12) = 37607912018。即使使用这些算法及其现代变体以及速度非常快的计算机,计算大的 pi 值仍然非常繁琐;在撰写本文时,已知的最大值为 pi(10^24) = 18435599767349200867866。
要使用此算法计算第 n 个素数,素数定理的推论将第 n 个素数 P(n) 限制在 n log n 和 n(log n + log log n) 之间,n > 5,因此计算pi 在边界处并使用二等分来确定第 n 个素数,当边界接近时切换到筛分。
我在博客的几个条目中讨论了质数。