【问题标题】:C Program (Prime Number in a given range)C程序(给定范围内的质数)
【发布时间】:2023-03-09 22:02:01
【问题描述】:

我已经开始学习 C 语言了。我编写了这个程序来查找给定范围内的所有素数,但我无法获得预期的输出。

谁能告诉我这个程序有什么问题?

#include <stdio.h>
#include <conio.h>

void main() {
    int min, max, i, j, count = 0;
    printf("Enter Your First Number\n");
    scanf("%d", &min);
    printf("Enter Your Last Number\n");
    scanf("%d", &max);
    for(i=min; i<=max; i++) {
        for(j=1; j<=i; j++) {
            if(i % j == 0) {
                count++;
            }
        }
        if(count==2) {
            printf("%d\t",i);
        }
    }
    getch();
}

【问题讨论】:

  • 您需要为每个候选人重置count
  • 除了@WeatherVane说的,如果你会写函数,最好创建一个isPrime函数。
  • i%j 对每个 i 和 j==1 || j==i 都为真。您应该在调试器中测试您的程序。在这里询问时,请始终提供一切,以便其他人可以重现问题。在您的情况下,缺少给定的输入、预期的输出和观察到的输出。 (见minimal reproducible example
  • 数字 0 和 1 被定义为非质数,但是,对于当前代码,当 min 的值是这些数字中的任何一个时,就会发生“坏”事情。

标签: c primes


【解决方案1】:

我只是建议摆脱 count 变量。

你怎么知道一个数 N 是否是素数?如果对于(2 到 N-1)范围内的每个 j,您都有 N%j != 0

所以:

  • 在内循环中,使用 j 从 2 到 N-1(而不是像您使用 tio 那样从 1 到 N)。实际上 N%1 和 N%N 将是 0
  • 您第一次找到j 使N % j == 0 中断。你确定它不是素数
  • 为什么要递增count?对于素数,j 计数器将等于i(因为您循环到j&lt;i,最后一个j++ 变为j 等于i)。所以只需检查j == i 并打印素数i
#include <stdio.h>
#include <conio.h>

int main( void )
{
    int min, max, i, j, count = 0;
    printf("Enter Your First Number\n");
    scanf("%d", &min);
    printf("Enter Your Last Number\n");
    scanf("%d", &max);

    for(i=min; i<=max; i++)
    {
        // Was for(j=1; j<=i; j++)
        for(j=2; j<i; j++)
        {
            if(i % j == 0)
            {
                //Was count++;
                break;
            }
        }

        //Was if(count==2)
        if(j == i)
        {
            printf("%d\t",i);
        }
    }
    getch();

    return 0;
}

【讨论】:

  • 注意不需要搜索到N - 1;直到并包括ceil(sqrt(max)) 就足够了。如果i是复合的,那么一个因子不大于√N,另一个不小于√N)。在你检查了“被 2 整除”之后,你可以只检查奇数。如果您在循环外检查“可被 3 整除”,那么对于从等于 1 的 K 开始的整数 K,所有较大的素数都具有 6K±1 的形式。限制搜索范围即使在 @987654342 @ 只是成千上万,更不用说更大了。使用“仅赔率”可以完成 1/2 的工作;使用 6K±1 做 1/3。
  • 如果要搜索的范围足够大(范围或最大值足够大),则构建一个 Eratosthenes 筛(或更高级的技术),以获取最大平方根的素数和那么只测试“已知的主要”可能因素可能是有益的。
  • @johnatanleffler 我承认我只关注 OP 的代码,以及我认为使其工作的最小修正,而不是担心效率。我知道奇数技术、sqrt(N) 限制和 Erathostenes 算法的筛子(但不知道 6k±1 标准。太好了!)。确认此评论,我的答案将消失(我已经打算在没有您的 cmets 的情况下这样做)
  • 除非您愿意,否则无需删除它。作为让 OP 运行的最小更改集,这很好。而 cmets 是短暂的;不要仅仅因为我发表评论而改变你所做的事情。如果有实质性的技术错误,那么我希望您注意,但是对于提供此类辅助信息的 cmets,请照常做。
【解决方案2】:

你来了。

#include <stdio.h>

int main( void ) 
{
    printf( "Enter the range of numbers (two unsigned integer numbers): " );

    unsigned int first = 0, last = 0;

    scanf( "%u %u", &first, &last );

    if ( last < first )
    {
        unsigned int tmp = first;
        first = last;
        last = tmp;
    }

    do
    {
        int prime = first % 2 == 0 ? first == 2 : first != 1;

        for ( unsigned int i = 3; prime && i <= first / i; i += 2 )
        {
            prime = first % i != 0;
        }

        if ( prime ) printf( "%u ", first ); 
    } while ( first++ != last );

    putchar( '\n' );

    return 0;
}

程序输出可能看起来像

Enter the range of numbers (two unsigned integer numbers): 0 100
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 

至于你的程序,你需要在内部循环之前重新初始化变量计数

for(i=min; i<=max; i++) {
    count = 0;
    for(j=1; j<=i; j++) {
        if(i % j == 0) {
            count++;
        }
    }

而且内循环效率低。

【讨论】:

    【解决方案3】:

    需要重置count的值。它从count=0 开始,然后对于任何输入,循环将向上计数。对于每个外循环索引,它会是这样的:

    • 1 (1%1=0 --> count++, count = 1)
    • 2 (2%1=0 --> count++, 和 2%2=0 --> count++, count = 3)
    • 3 (3%1=0 --> count++, 和 3%3=0 --> count++, count = 5)

    等等...直到到达max

    【讨论】:

      【解决方案4】:

      您可以使用一个简单的 isprime 函数来检查一个数字是否为素数,然后在给定的区间内调用该函数。
      要判断一个数是否为素数,我们可以使用简单的素数测试来检查它。

      #include <stdio.h>
      #include <stdlib.h>
      #include <stdbool.h>
      
      
      bool isprime(int n)
      {
           if(n <= 1) return false;
           if(n <= 3) return true;
      
           if(n%2 == 0 || n%3 == 0) return false;
      
           for(int i = 5;i*i <= n;i += 6)
           {
              if(n%i == 0 || n%(i + 2) == 0)
              {
                  return false;
              }
           }
           return true;
       }
      
      
      
      int main()
      {
          int a,b;
          printf("Enter the first number :");
          scanf("%d",&a);
          printf("Enter the second number :");
          scanf("%d",&b);
          for(int i = a;i <= b;i++)
          {
             if(isprime(i)) printf("%d ",i);
          }
          return 0;
       }
      

      【讨论】:

        【解决方案5】:

        你应该做一个简单的改变:

        #include <stdio.h>
        #include <conio.h>
        
        void main() {
            int min, max, i, j, count;
            printf("Enter Your First Number\n");
            scanf("%d", &min);
            printf("Enter Your Last Number\n");
            scanf("%d", &max);
            for(i=min; i<=max; i++)
            {
                count=1;
                for(j=2; j<=i; j++) 
                {
                    if(i % j == 0) {
                    count++;
                    }
                }
                if(count==2) {
                    printf("%d\t",i);
                }
            }
        }
        

        【讨论】:

        • 是什么让您的答案与众不同?在各个方面已经有了更好的答案:使其工作的最小更改、可能的改进和解释。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 2011-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-25
        相关资源
        最近更新 更多