簡體   English   中英

質數搜索算法(兩種不同的算法)和質數表的使用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM