[英]Prime number search algorithm (two different algorithm) and use of prime tables
我編寫了兩種算法來查找素數。 一個isPrime()
-基於從3到奇數的平方根的奇數除數進行分析(偶數被丟棄),第二個isPrime2()
-基於所有素數都更大的假設大於3的形式為:p = k * 6-1或p = k * 6 + 1。 (這些函數認為數字1是質數,但是如果您認為1不是質數,則很容易修改此行為!)
第二種算法比第一種算法快一點,但是使用表時它們至少具有相同的速度。
使用表(如下面的main()一樣)比不使用表的搜索快兩倍(搜索前百萬個素數)。 您可以驗證是否確實在while
循環中修改了對isPrime()
函數的調用,如下所示:
isPrime(n, NULL);
代替:
isPrime(n, &tbl[x]);
主()加載包含的素數的一百萬,一個使用兩個素數表isPrime()
並使用另一種isPrime2()
然后打印輸出所使用的時間和一些素數。 之后,main()比較兩個表的結果。
我對填充素數表(也從1開始)並確定大/否數是素數的算法感興趣。 有什么建議嗎? 您知道不同或更快的算法嗎?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <sys/time.h>
typedef struct prime_table {
uint64_t * primes;
uint32_t inTable;
uint32_t maxIn;
} table;
int isPrime(uint64_t n, table * t)
{
uint64_t i, k, m;
if(!n)
return 0;
if(n < 4)
return 1;
if(!(n & 1)) /* the number is even */
return 0;
m = sqrt(n);
k = 1;
if(t) {
for(i = 2; i < t->inTable && t->primes[i] <= m; i++) {
k = t->primes[i];
if(!(n % k))
return 0;
}
}
k += 2;
for(i = k; i <= m; i += 2) {
if(!(n % i))
return 0;
}
return 1;
}
int isPrime2(uint64_t n, table * t)
{
uint64_t i, k, m;
if(!n)
return 0;
if(n < 4 || n == 5)
return 1;
if(!(n & 1)) /* the number is even */
return 0;
if(!(n % 3))
return 0;
k = (n - 1) / 6; m = (n + 1) / 6;
if(k * 6 + 1 != n && m * 6 - 1 != n)
return 0;
m = sqrt(n);
k = 5;
if(t) {
for(i = 3; i < t->inTable && t->primes[i] <= m; i++) {
k = t->primes[i];
if(!(n % k))
return 0;
}
}
k += 2;
k = (k - 1) / 6; m = (m + 1) / 6;
for(i = k; i <= m; i++) {
if(!(n % (6 * i - 1)) || !(n % (6 * i + 1)))
return 0;
}
return 1;
}
uint32_t getusec()
{
struct timeval t;
gettimeofday(&t, NULL);
return (t.tv_sec * 1000000UL + t.tv_usec);
}
int main(void)
{
static table tbl[2];
uint64_t n = 1;
uint32_t t, i, j;
/* Init two prime tables */
for(i = 0; i < 2; i++) {
tbl[i].maxIn = 1000000;
tbl[i].primes = malloc(tbl[i].maxIn * sizeof(*tbl[0].primes));
/* Load the 1,2 and 3 into the table */
for(j = 1; j < 4; j++)
tbl[i].primes[j - 1] = j;
tbl[i].inTable = 3;
}
/* Loading table with isPrime()*/
t = getusec();
n = 3;
while(tbl[0].inTable < tbl[0].maxIn) {
n += 2;
if(isPrime(n, &tbl[0])) {
tbl[0].primes[tbl[0].inTable++] = n;
}
}
printf("%u primes computed in %u usec\n", tbl[0].inTable, getusec() - t);
puts("First 16 computed primes");
for(i = 0; i < 16; i++)
printf("%9lu ", tbl[0].primes[i]);
puts("\n--------------------");
puts("Last 16 computed primes");
for(i = tbl[0].inTable - 16; i < tbl[0].inTable; i++)
printf("%9lu ", tbl[0].primes[i]);
puts("\n--------------------");
/* Loading table with isPrime2()*/
t = getusec();
n = 3;
while(tbl[1].inTable < tbl[1].maxIn) {
n += 2;
if(isPrime2(n, &tbl[1])) {
tbl[1].primes[tbl[1].inTable++] = n;
}
}
printf("%u primes computed in %u usec\n", tbl[1].inTable, getusec() - t);
puts("First 16 computed primes");
for(i = 0; i < 16; i++)
printf("%9lu ", tbl[1].primes[i]);
puts("\n--------------------");
puts("Last 16 computed primes");
for(i = tbl[1].inTable - 16; i < tbl[1].inTable; i++)
printf("%9lu ", tbl[1].primes[i]);
puts("\n--------------------");
puts("Searching for differences in tables");
for(i = 0; i < tbl[0].inTable; i++) {
if(tbl[0].primes[i] != tbl[1].primes[i]) {
printf("%u %lu %lu", i, tbl[0].primes[i], tbl[1].primes[i]);
break;
}
}
if(i == tbl[0].inTable) {
puts("No differences have been found!");
}
puts("--------------------");
return 0;
}
根據輸入值,但是如果您想提高效率,一種已知的解決方案是使用Eratosthenes篩網 。
篩子類似於“檢查是否存在奇數除數”的概念-為什么只有奇數? 因為只有偶數是2。類似地,您可以為3,5和任何其他素數執行此操作。
篩子會動態找到這些素數,並丟棄受每個素數影響的所有非素數。
如果您要檢查單個大數是否為質數,那么實際上有一個有效的解決方案,該解決方案可以在代表數字的位數的多項式時間內(即數字對數的多項式)運行,即AKS
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.