我正在寻找一种找到最接近的质数的方法。无论是大于还是小于,只要最接近即可(最好不会溢出)。至于速度,如果它能在1GHz计算机上的软件中大约50毫秒内计算完成(在Linux内部运行),我将非常高兴。
我正在寻找一种找到最接近的质数的方法。无论是大于还是小于,只要最接近即可(最好不会溢出)。至于速度,如果它能在1GHz计算机上的软件中大约50毫秒内计算完成(在Linux内部运行),我将非常高兴。
此外:质数乘积 {2、3、5、7、11、13、17、19、23} = (223092870)。明确测试 [2,23] 中的任何候选项。计算最大公约数:g = gcd(u, 223092870UL)
。如果 (g != 1)
,则该候选项为合成数。如果 (g == 1 && u < (29 * 29))
,则该候选项(u > 23
)绝对是质数。否则,继续进行更昂贵的测试。使用32位算术进行单个gcd测试非常便宜,并且根据Mertens' (?)定理,这将检测到 ~68.4%的所有奇合成数。
{29, 31, 37, 41, 43}
,它们的乘积是58642669
。等等等等。但是每组中的质数数量会缩小,因为最终乘积将超过32位。 - Jesse Chisholm#include <iostream>
#include <cmath>
#include <climits>
#include <cassert>
using namespace std;
typedef unsigned int UI;
const UI MAX_SM_PRIME = 1 << 16;
const UI MAX_N_SM_PRIMES = 7000;
const UI WINDOW = 256;
void getSMPrimes(UI primes[]) {
UI pos = 0;
primes[pos++] = 2;
bool mark[MAX_SM_PRIME / 2] = {false};
UI V_SM_LIM = UI(sqrt(MAX_SM_PRIME / 2));
for (UI i = 0, p = 3; i < MAX_SM_PRIME / 2; ++i, p += 2)
if (!mark[i]) {
primes[pos++] = p;
if (i < V_SM_LIM)
for (UI j = p*i + p + i; j < MAX_SM_PRIME/2; j += p)
mark[j] = true;
}
}
UI primeNear(UI n, UI min, UI max, const UI primes[]) {
bool mark[2*WINDOW + 1] = {false};
if (min == 0) mark[0] = true;
if (min <= 1) mark[1-min] = true;
assert(min <= n);
assert(n <= max);
assert(max-min <= 2*WINDOW);
UI maxP = UI(sqrt(max));
for (int i = 0; primes[i] <= maxP; ++i) {
UI p = primes[i], k = min / p;
if (k < p) k = p;
UI mult = p*k;
if (min <= mult)
mark[mult-min] = true;
while (mult <= max-p) {
mult += p;
mark[mult-min] = true;
}
}
for (UI s = 0; (s <= n-min) || (s <= max-n); ++s)
if ((s <= n-min) && !mark[n-s-min])
return n-s;
else if ((s <= max-n) && !mark[n+s-min])
return n+s;
return 0;
}
int main() {
UI primes[MAX_N_SM_PRIMES];
getSMPrimes(primes);
UI n;
while (cin >> n) {
UI win_min = (n >= WINDOW) ? (n-WINDOW) : 0;
UI win_max = (n <= UINT_MAX-WINDOW) ? (n+WINDOW) : UINT_MAX;
if (!win_min)
win_max = 2*WINDOW;
else if (win_max == UINT_MAX)
win_min = win_max-2*WINDOW;
UI p = primeNear(n, win_min, win_max, primes);
cout << "found nearby prime " << p << " from window " << win_min << ' ' << win_max << '\n';
}
}
a
足够小的情况下使用二分查找。 - Mark Ransom