我正在尝试优化素数搜索算法。
我有一个程序可以找到(实际计数)低于某个限制的素数。我知道素数可以6k+1
的形式6k-1
,k > 0
表示。
对于目前的时间,我使用筛分算法将非素数分类。一些伪代码:
int P[100] = {1};
int m = 100;
int n = 2, k, i, j, sqrtm = (int)sqrt(m);
for(k = 2, i = 5; i < sqrtm + 1; i += k, k ^= 6)
if(P[i])
P[i] = 0;
n = n + 1;
for(j = i * i; j < m; j += 2 * i)
P[j] = 0;
for(k = 2, i = 5; i < m + 1; i += k, k ^= 6)
if(P[i])n = n + 1;
print n;
以上代码有望打印出小于m的质数。 我在这里和那里使用一些技巧来加快速度。例如,从'5'开始筛选非质数,使用这样的事实,即上述形式的质数不能为'2'和'3'的倍数。 6k + 2是偶数。 6k + 3是'3'的倍数,令x = 2k,6k + 3 => 3x + 3 => 3(x + 1)mod 3 == 0或3(2k + 1)mod 3 == 0。
在这里,我的问题出现了。如果我用一些质数进行预筛分,是否可以采用其他形式的质数来加快筛分循环? 例如,预先筛分2,3,5,7,11,13,17,19,23,29。因此,现在P数组没有以上的倍数。也许有人可以建议我某种形式的质数形式,例如,通过预筛分,可以完成更大的循环。
我已经做了一些与素数形式无关的优化。就像大块筛分并使用位集存储筛分一样。所有这些使我的程序运行起来非常快。
time ./np 1000000000
allocated 119Mb
primes from 2 <= 1000000000 : 50847534
real 0m2.386s
user 0m2.354s
sys 0m0.032s
我知道我可以从互联网上获得更好的素数计数器程序。而且它将运行得更快。但是我只想知道我自己可以走多远。和社区帮助;)
总结一下。我想使用预筛分。我认为它使我的比较更少,总的内部循环也更少。我问你,在知道筛分前的事实的情况下,如何用其他形式写素数?
答案 0 :(得分:3)
您说,除了2
和3
以外,所有质数均采用2*3*k±1
的形式(对于某些整数k> = 1)
您可以将其扩展到
2 * 3 * 5 * k±{1、7、11、13}(和2、3、5、7、11、13)
或
2 * 3 * 5 * 7 * k±{1、11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73, 79、83、89、97、101、103、107、109}(以及2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、53 59,61,67,71,73,79,83,89,97)
实施此表格可能不会使您的程序更高效(但是您定义的效率更高)。您需要测量。
上面的值是直接通过移动电话输入的,而无需验证。使用后果自负。