簡體   English   中英

C 中的質數生成器

[英]Prime Number Generator in C

這是問題的鏈接: http : //www.spoj.com/problems/PRIME1/

基本上我們得到兩個限制,我們必須打印出它們之間的所有素數......

這是我的代碼(語言 == C):

#include <stdio.h>

void IsPrime(int test){
    for(int i= 2; i<test; i++){
        if(test%i==0){
            return;
        }
    }
    printf("%d\n",test);
}

int main(){
    int T,lower,upper;
    scanf("%d",&T);

    while(T--){
        scanf("%d",&lower);
        scanf("%d",&upper);

        for(int i = lower;i<=upper;i++){
            if(i>1){
            IsPrime(i);
            }
        }  
    }
return 0;
}

在我的本地機器上,我運行了它,它適用於簡單的測試用例......我來自網站的消息是超時錯誤,所以我想知道是否有更有效的方法來解決這個問題,因為顯然我解決的速度不夠快?

首先,你不必檢查n中的每個數字來確定n是否為素數,只有它的平方根(有一個數學證明,現在不給它)。 所以:

void IsPrime(int test){
    // i <= sqrt(test)
    // but to avoid sqrt you can do i * i <= test
    for(int i= 2; i * i <= test; i++){
        if(test%i==0){
            return;
        }
    }
    printf("%d\n",test);
}

接下來,我們知道在2之后,所有其他素數都是奇數,所以如果我們將2視為特例,我們可以循環2:

// Do greater than one check only once
if (lower > 1) {
    // Special case - lower is 2
    if (lower == 2) {
        printf("%d\n", 2);
        ++lower;
    }

    for(int i = lower; i <= upper; i += 2){
        IsPrime(i);
    }
}

但是,由於你必須做T次,所以你最終會做的不僅僅是需要的檢查。 此外,這個問題限制了n和m,所以它基本上是完美的篩子,正如@HennoBrandsma所說。

使用這些優化,您應該找到所有素數到限制,並將它們存儲在容器中。 然后,當提示范圍時,只需移動篩子並打印出數字。

(這將要求您更多地更改IsPrime功能 - 而不是立即打印數字,讓它返回true或false,然后根據它,將數字添加到容器中)

您可以嘗試以下方法,對測試次數進行略微優化,並跳過任何大於2偶數值:

int isprime (int v)
{
    int i;

    if (v < 0) v = -v;                          /* insure v non-negative */
    if (v < 2 || !((unsigned)v & 1))    /* 0, 1 + even > 2 are not prime */
        return 0;

    if (v == 2) return 1;

    for (i = 3; i * i <= v; i+=2)
        if (v % i == 0)
            return 0;

    return 1;
}

如果您可以使用數學庫和math.h ,以下可能會更快:

int isprime (int v)
{
    int i;

    if (v < 0) v = -v;                          /* insure v non-negative */
    if (v < 2 || !((unsigned)v & 1))    /* 0, 1 + even > 2 are not prime */
        return 0;

    if (v == 2) return 1;

    for (i = 3; i <= sqrt (v); i+=2)
        if (v % i == 0)
            return 0;

    return 1;
}

我將這兩個版本的時間定義在int范圍內的值為1-2百萬之間並且它們很接近。

注意:在使用重復調用的實際測試中, i * i <= v (下面的isprime2 )的版本始終比使用i <= sqrt (v) (下面的isprime3 )的調用快。 例如:

$ ./bin/isprimetst2
  isprime  (1.650138 sec) - 78497 primes
  isprime2 (0.805816 sec) - 78497 primes
  isprime3 (0.983928 sec) - 78497 primes

短驅動程序遍歷0-2000000所有素數,例如:

r = 0;
t1 = clock ();
for (v = 0; v < 2000000 - 1; v++) r += isprime2 (v);
t2 = clock ();
printf (" isprime2 (%lf sec) - %u primes\n", (t2-t1)/CLOCKS_PER_SEC, r);

r = 0;
t1 = clock ();
for (v = 0; v < 2000000 - 1; v++) r += isprime3 (v);
t2 = clock ();
printf (" isprime3 (%lf sec) - %u primes\n", (t2-t1)/CLOCKS_PER_SEC, r);

您可以在C中使用庫maths.h並使用sqrt函數計算給定數字的平方根。 所以程序可能是這樣的:

#include <stdio.h>
#include <maths.h>

int isPrime(int number){
    int i;
    if(number % 2 == 0){
        return;
    }

    for(i=3; i<=sqrt(number); i++){
        if(number % i == 0){
            return;
    }
    printf("%d\n",number);
}

int main(){
    int lower,upper,i;
    if(lower >1){
        if(lower == 2){
            printf("2\n");
        }

        for(i=lower; i<=upper; i++){
            isPrime(i);
        }
    return 0;
}

簡而言之,您可以使用if-else條件來使用一些額外的檢查(如if(number%2 == 0))來降低程序的時間復雜度。例如,一個新的if條件可能是if(number%5 == 0) )等等,所以在這些條件的幫助下,檢查不會在許多情況下進行循環,這會減少程序的時間。

#include<stdio.h>
int main()
{
    int low,high,j;
    int prime(int);
    int t;
    scanf("%d",&t);
    while (t>0)
    {
        scanf("%d %d",&low,&high);
        while (low<=1)
        {
            low++;
            continue;
        }
        for (j=low;j<=high;j++)
        {
            if (prime(j)){
                printf("%d\n",j);
            }
        }
        printf("\n");
        t--;
    }
    return 0;
}

int prime(int n)
{
    int i;
    for (i=2;i*i<=n;i++)
    {
        if (n%i==0){
            return 0;
        }
    }
    return 1;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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