得到所有素数

时间:2017-02-27 19:24:54

标签: c loops primes

我试图从1到10获取所有素数。我的代码不起作用,有人可以告诉我为什么吗?

#include<stdio.h>

int main(void) {

    int i = 10;
    int n = 10;

    for(; i > 1; i-- ) {
        while(n > 1) {
            if((i % (n - 1)) == 0) {
                printf("%d is not a prime number", i);
                break;
                n--;
            }
        }
        n = 10;
        printf("%d is a prime number", i);
    }
    return 0;
}

获得非常大的计算时间而没有输出。

7 个答案:

答案 0 :(得分:1)

我们初学者应该互相帮助。

这是一个示范程序,我尽量使用你的方法。

#include <stdio.h>

int main(void) 
{
    const int N = 10;

    for ( int i = N; i > 1; i-- ) 
    {
        int n = i - 1;
        while ( n > 1 && i % n != 0 ) n--; 

        if ( n == 1 )
        {
            printf("%d is a prime number\n", i);
        }
        else
        {
            printf("%d is not a prime number\n", i);
        }
    }

    return 0;
}

程序输出

10 is not a prime number
9 is not a prime number
8 is not a prime number
7 is a prime number
6 is not a prime number
5 is a prime number
4 is not a prime number
3 is a prime number
2 is a prime number

使用任意正值设置常量N,您可以获得N之前的所有素数。

至于你的程序,那么你应该将第一个语句放在内部循环之外的printf。此语句n--;也必须遵循if语句。当i等于2且n也等于2时,您将得到2不是素数,因为此表达式i % (n - 1)) == 0为真。

您可以编写一个单独的函数来检查给定的数字是否为素数。 你来了。

#include <stdio.h>

int is_prime( unsigned int n )
{
    int prime = ( n == 2 ) || ( n != 1 && n % 2 );

    for ( unsigned i = 3; prime && i <= n / i; i += 2 )
    {
        prime = n % i;
    }

    return prime;
}

int main( void ) 
{
    while ( 1 )
    {
        unsigned int n;

        printf( "Enter a non-negative number (0 - exit): " );

        if ( scanf( "%u", &n ) != 1 || n == 0 ) break;

        printf( "\nPrime numbers up to %u:", n );

        for ( unsigned int i = 0; i < n; i++ )
        {
            if ( is_prime( i + 1 ) ) printf( " %u", i + 1 );
        }

        printf( "\n\n" );
    }

    return 0;
}

答案 1 :(得分:1)

As @Zaid pointed out,无限循环是由n--语句中的if引起的。 if条件最终会失败,因此最终会陷入无限循环。

事实证明,内部while循环是另一个for循环。

for( n = 10; n > 1; n-- )

这种错误是使用循环的原因,它清楚地说明了初始化,终止条件和递增。

这不会使代码工作,但它不是无限的。

你基本上要做的就是每个数字,尝试将它除以每个低于自身的数字。

for( i = 10; i > 1; i-- ) {  // every number from 10 to 2
    for( n = i-1; n > 1; n-- ) { // every number lower than i to 2.
        if( i % n == 0 ) {
            printf("%d is not a prime number\n", i);
            break;
        }
    }

    // If n reached 1, it made it through the sieve.
    if( n <= 1 ) {
        printf("%d is a prime number\n", i);
    }
}

请注意,通过在i - 1处开始n,不需要记住将i与n - 1进行比较。这简化了代码,并且它是一个较少的潜在错误。

有几种方法可以优化它。我们可以观察一些事情:

当n&gt;时,整数永远不会被完全整除。 I / 2。所以10永远不会被9,8,7或6整除。这意味着我们可以在i / 2处开始计数n并保存一堆检查。由于这是整数除法,因此i / 2将始终向下舍入,我们无需自己完成。

原始除数越小,它越有可能成为除数。一半的数字可被2整除,1/3可被3整除,1/5乘5 ...所以从底部开始并增加n的速度更快。

#include<stdio.h>

int main(void) {
    int num;
    int divisor;

    // From 10 to 2.
    for( num = 10; num > 1; num-- ) {
        // From 2 to num/2, no need to go further.
        for( divisor = 2; divisor <= num/2; divisor++ ) {
            if( num % divisor == 0 ) {
                printf("%d is not a prime number\n", num);
                break;
            }
        }

        // If we got past num/2 it's prime
        if( divisor > num/2 ) {
            printf("%d is a prime number\n", num);
        }
    }

    return 0;
}

我们可以更进一步,观察偶数不是素数。这意味着偶数也不是主要的除数。如果我们从一个奇数开始n,我们可以再次将检查次数减半。如果我们完全跳过偶数,这很容易。

#include<stdio.h>

int main(void) {
    int num;
    int divisor;

    // Count down from 11 by 2s.
    for( num = 11; num > 1; num -= 2 ) {
        // From 3 to num/2. No need to check 2, we skipped even numbers.
        for( divisor = 3; divisor <= num/2; divisor += 2 ) {
            if( num % divisor == 0 ) {
                printf("%d is not a prime number\n", num);
                break;
            }
        }

        // Same end condition as before.
        if( divisor > num/2 ) {
            printf("%d is a prime number\n", num);
        }
    }

    // Special case for 2.
    printf("2 is a prime number\n");

    return 0;
}

如果您想要所有数字,可以在主循环中放置一个特殊情况来检查它是否均匀。同样,2是特殊的,所以我们不必在循环内不断检查num!= 2。

#include<stdio.h>

int main(void) {
    int num;
    int divisor;

    // Count down from 10 to 3, 2 is special cased.
    for( num = 10; num > 2; num-- ) {
        // Special case for even numbers so we can still do the
        // for loop by 2s.
        if( num % 2 == 0 ) {
            printf("%d is not a prime number\n", num);
            continue;
        }

        // 3 to num/2, odd numbers only.
        for( divisor = 3; divisor <= num/2; divisor += 2 ) {
            if( num % divisor == 0 ) {
                printf("%d is not a prime number\n", num);
                break;
            }
        }

        if( divisor > num/2 ) {
            printf("%d is a prime number\n", num);
        }
    }

    // Again, special case for 2 to reduce code operations inside the loop
    printf("2 is a prime number\n");

    return 0;
}

答案 2 :(得分:0)

您的while循环进入无限循环,因为您在n语句块中递减if

n--的结束括号放在if块内,并在循环

答案 3 :(得分:0)

见下面的修复。
主要问题:

  1. 您的程序未结束的原因固定在第一个while循环内的if语句中 - 请考虑i = 10n-1 = 9。在这种情况下,if语句将解析为false,程序将无休止地循环,因为n--永远不会发生。
  2. 即使您的计划确实结束了,也会为所有非素数打印%d is not a prime number%d is a prime number(为什么?)
  3. 由于您的模数约为n-1n递减为2,因此您测试的每个数字都将是非素数(您正在测试i%1
  4. 除此之外 - 你一切都很好(;

    #include<stdio.h>
    
    int main(void) {
        int i;
        int n;
    
        for(i = 10; i > 1; i-- ) {
            n = i;
            while( n > 2 ) {
                if( ( i % ( n-1 ) ) == 0 ) {
                    printf( "%d is not a prime number\n", i );
                    break;
                }
                n--;
            }
            if (n == 2)
                printf( "%d is a prime number\n" , i );
        }
        return 0;
    }
    

答案 4 :(得分:0)

你的逻辑错了,请尝试以下方法:

#include<stdio.h>

int main(void) {
    int i = 10;
    for(; i > 1; i-- ) {
        int n = 10;
        int flag = 0;
        while(n > 2) {
            if((i % (n - 1)) == 0) {
                flag = 1; 
                printf("%d is not a prime number", i);
                break;
            }
            n--;
        }
        if(flag == 0) { 
            printf("%d is a prime number", i);
        } 
    }
    return 0;
}

有一个问题是因为你在破坏后进行了推测,这没有任何意义

编辑:我刚刚意识到这将始终打印“是一个素数”,你需要设置一个标志来告诉你它是不是素数。

答案 5 :(得分:0)

希望我没有回答你的功课问题,但是......

#include<stdio.h>

int main() {

int i = 10;
int n = 10;

for(i=10; i>1; i--)  {
    n=i;                       
    while( n > 1 ) {
        /* You also need to check to make sure that you aren't checking for 1 here. */
        if( ( i % ( n-1 ) ) == 0 && (n-1 !=1)) {
            printf("\n\n %d is not a prime number",i);
            break;
        }
        n--; /* This is culprit number one, your control operator is never being hit because it is after the break statement */
        if (n==1){
           /* n==1 means This should never be called unless the entire loop has proven every other number has been checked */
           printf( "\n\n %d is a prime number" , i );
        }
    }
}
return 0;

}

答案 6 :(得分:0)

这样做的简单而可靠的方法如下:

#include<stdio.h>
int main(){
    int i,a;
    for(i=2;i<=10;i++){
        for(a=2;a<i;a++)
             if(a%i==0)
                 break;
        if(a==i)
             printf("%d is a prime number",i);
     }
    return 0;
}