簡體   English   中英

查找素數的程序打印出兩個

[英]Program to find prime numbers prints out two

我是編程的新手,我想嘗試編寫一個程序來查找一定范圍內的質數。 當我通過編譯器運行該程序時,沒有出現任何錯誤,但是當我嘗試實際運行該程序時,它說只有2個,這是不正確的。 我認為應該是168。如果您能指出我的錯誤,我將不勝感激。 提前致謝!

#include <stdio.h>
#include <math.h>

void primeFinder(void);

int main(void)
{
    printf("Prime numbers from 1 to 1000:\n\n");
    primeFinder();

    return 0;
}


void primeFinder(void)
{
    int i;
    int j;
    int k;
    int n_primes = 0;

    //i is the number to be tested:
    for ( i = 2 ; i <= 1000 ; i++ )
    {
        //i must be divided by j, that goes from 2 to i - 1 [(i - 2) divisions]:
        for ( j = 2, k = 0 ; j <= sqrt(i) ; j++ )
        {
            //i is not prime, whatever is the value of j:
            if ( i % j == 0 )
            {
                //If remainder is 0, there is no need to test that i anymore:
                break;
            }
            else
            {
                k++;
            }

        } //End of inner for
            //i is prime:
        if ( k == i - 2 )
        {
            printf("%d\t", i);
            n_primes++;
        }
    } //End of outer for
    printf("\n\nIt was found %d prime(s) in the inverval considered.\n", n_primes);
}

我給初學者程序員一個我發現實際上有幫助的建議是:“考慮模塊化 !” 換句話說,訓練自己去分裂和征服。 如何將問題分解為基本要素?

一個適合您程序的框架如下:

#include <stdio.h>

typedef int BOOL;

#define TRUE 1
#define FALSE 0    

BOOL is_prime(int number);

int main()
{
    printf("Prime numbers between 1 and 1000:\n");

    int i;
    for (i = 1; i <= 1000; ++i)
    {
        if (is_prime(i))
        {
            printf("%d\n", i);
        }
    }

    return 0;
}

// ...

這是因為以后如果需要確定數字是否為質數,則只需復制並粘貼現有的實現即可。

這是我經常使用的is_prime一種實現,並且做得很好:

BOOL is_prime(int number)
{
    // If the number is less than two, then it is not prime.
    if (number < 2)
    {
        return FALSE;
    }

    // If the number is two, then it is prime.
    if (number == 2)
    {
        return TRUE;
    }

    // If the number is even, then it is not prime.
    if (number % 2 == 0)
    {
        return FALSE;
    }

    // Try and divide the number by all odd numbers
    // less than or equal to its square root. If
    // we can, then it is not prime. Otherwise, it is.
    int i;
    for (i = 3; i * i <= number; i += 2)
    {
        if (number % i == 0)
        {
            return FALSE;
        }
    }
    return TRUE;
}

if ( k == i - 2 )此檢查是錯誤的,則前一個塊僅針對sqrt(i) - 2數字循環。 您需要檢查sqrt(i) -2

j到達i平方根后,退出內部循環。 因此, k不會計算不除i的整數的總數。

為什么還要跟蹤k 只需設置一個標志來告訴您數字是否為素數:

#include <stdio.h>
#include <stdbool.h>
#include <math.h>

int num_primes(int limit) {
    int i;
    int j;
    int n_primes = 0;
    bool is_prime; /* note stdbool.h in the includes */

    for (i = 2; i <= limit; i++) {
        is_prime = true;
        for (j = 2; j <= sqrt(i); j++) {
            if (i % j == 0) {
                is_prime = false;
                break;
            }
        }
        /* This could be written as `if (is_prime) n_primes++;` */
        n_primes += is_prime;
    }
    return n_primes;
}

這是您的支票。 您執行此操作的方式有些奇怪。 我認為更簡單的方法是創建一個標志並將其設置為true。 因此,您假設數字為素數。 在瀏覽過程中,如果發現數字不是素數,請將標志設置為false。 之后,檢查標志是否仍然為真,並打印結果。 這就是我在說的:

  int i;
int j;
int k;
int n_primes = 0;
bool flag;

//i is the number to be tested:
for ( i = 2 ; i <= 1000 ; i++ )
{
    //Assume it's prime
    flag=true;
    //i must be divided by j, that goes from 2 to i - 1 [(i - 2) divisions]:
    for ( j = 2 ; j <= sqrt((double)i) ; j++ )
    {
        //i is not prime, whatever is the value of j:
        if ( i % j == 0 )
        {
            //If remainder is 0, there is no need to test that i anymore:
            flag=false;
            break;
        }
    } //End of inner for
        //i is prime:
    if ( flag==true )
    {
        printf("%d\t", i);
        n_primes++;
    }
} //End of outer for
printf("\n\nIt was found %d prime(s) in the inverval considered.\n", n_primes);

似乎您在中間更改了算法,即,您直到sqrt(i)都進行了測試,而不是檢查直到i-1除數(這很浪費sqrt(i)

問題是您僅更改了循環條件,但沒有更新以下條件:

if ( k == i - 2 )

您有2個選擇:

  1. 回滾到朴素算法,並將循環條件更改為:

    for( j = 2, k = 0 ; j <= i-1 ; j++ )

  2. 更改程序邏輯,以便您僅需要知道除數是否存在 1以外的除數,而與此類除數的數量無關。

如果數字是素數,則k將增加到sqrt(i)的值。 如您所見,if條件並不總是正確的。

無需使用計數器,您只需要一個標志即可知道它是否為素數。 也許是這樣的:

    //i must be divided by j, that goes from 2 to i - 1 [(i - 2) divisions]:
    for ( j = 2, k = 1 ; j <= sqrt(i) ; j++ )
    {
        //i is not prime, whatever is the value of j:
        if ( i % j == 0 )
        {
            //If remainder is 0, there is no need to test that i anymore:
            k = 0;
            break;
        }
    } //End of inner for
    if (k) // i is prime
    {
    ...

問題出在

if ( k == i - 2 )

i的值是固定的,而k是可變的。 因此,以下幾行僅針對i = 2和3執行。因此,您得到的答案是2。

if ( k == i - 2 )
{
      printf("%d\t", i);
      n_primes++;
}

您可能會發現以下代碼有用:

#include<stdio.h>
#include<math.h>
#define TRUE 1
#define FALSE 0
int isPrimeNumber(int num)
{
    int i=2;
    int len=sqrt(num);
    if(num<2) return FALSE;
    while(i<=len)
    {
        if(num%i==0)
        {
            return FALSE;
        }
        i++;
    }

    return TRUE;
}

int countPrimeNumbersInRange(int start, int end)
{
    int count=0;
    while(start<=end)
    {
        if(isPrimeNumber(start))
        {
            printf("%d\t",start);
            count++;
        }
        start++;
    }
    return count;
}

int main()
{
    printf("\n\nIt was found %d prime(s) in the inverval considered.\n", countPrimeNumbersInRange(1, 1000));
    return 0;
}

暫無
暫無

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

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