我查找素数的代码不起作用。这是怎么了

时间:2019-07-13 22:40:29

标签: c

我正在尝试找到最大为1000的素数,但是我只能得到2和3。

void main()
{
    int i = 1, j, n = 1000;

    while (n != 0)
    {
        j = 2;
        i++;
        if (i % j != 0)
        {
            j++;
        }

        if (i == j)
        {
            printf("%d\n", i);
            n--;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您的代码中存在问题:

  • 您应该#include <stdio.h>

  • main的原型不正确,应该返回int

  • 您应该在循环外部初始化j并以略有不同的顺序运行测试。

  • 该代码并非旨在查找最多1000个素数,而是查找前1000个素数。

这是更正的版本:

#include <stdio.h>

// print the first 1000 prime numbers
int main() {
    int i = 2, j = 2, n = 1000;

    while (n != 0) {
        if (i % j == 0) {
            if (i == j) {
                printf("%d\n", i);
                n--;
            }
            j = 2;
            i++;
        } else {
            j++;
        }
    }
    return 0;
}

但是请注意,您的算法令人困惑且效率低下:

  • 您可以将一个循环实际上组合为2个嵌套循环。

  • 您可以测试所有除数到i的除数,而您可以在j * j > i时停止,从而将时间复杂度从 O(N 2 ) / strong>更改为 O(N 1.5

  • 您还可以使用特殊情况2,并且仅测试奇数和除数,从而将除法数进一步减少。

这里是替代方法:

#include <stdio.h>

// print the first 1000 prime numbers
int main() {
    int i, j, n = 1000;

    if (n > 0) {
        printf("%d\n", 2);
        n--;
    }

    i = 3;
    while (n > 0) {
        for (j = 3;; j += 2) {
            if (j * j > i) {
                printf("%d\n", i);
                n--;
                break;
            }
            if (i % j == 0)
                break;
        }
        i += 2;
    }
    return 0;
}

答案 1 :(得分:0)

您的代码执行错误的逻辑。它不会在每个n都没有余数的情况下寻找第一个除数。

要搜索素数,您必须对没有小于给定整数的整数除数的每个数字进行个体化,换句话说:如果给定数字除以所有可能的除数(小于该整数),则会生成余数(余数)不为0)是素数。

尝试这种方式:

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

/* Computes all primes from 1 to 1000 */
int main(void)
{
    int i,j,n=3; /* n=3 3 is the first odd number to test */

    /* 2 is the only even prime number */
    printf("%4d ",2);

    while(n<1000) {
        /* j=max usefull divisor */
        j=(int)sqrt(n);

        /* scanning divisors (i is the divisor)*/
        for(i=3;i<=j && (n%i);i+=2);

        /* if no divisor found print the number */
        if (i>j) {
            printf("%4d ",n);
        }

        /* Test the next odd number */
        n+=2;
    }
    puts("");
    return 0;
}

此代码包含3个技巧:

  • 2是唯一的偶数素数。

  • 如果数字的平方根内没有除数,则为质数。

  • 我们仅测试奇数(n=3; ... n+=2;),然后除数可能只是奇数(i=3; ... i+=2

按照您的意图和@Chqrlie所说的,我做了另一个版本:

#include <stdio.h>

/* Computes first 1000 primes */
int main(void)
{
    int i,n=3, cnt = 1000; /* n=3 3 is the first odd number to test */
    /* 2 is the only even prime number */
    printf("%4d ",2);
    cnt--; /* 2 was already written */

    while(cnt) {
        /* scanning divisors (i is the divisor)*/
        for(i=3;i*i<n && (n%i);i+=2);

        /* if no divisor found print the number */
        if (i*i>n) {
            printf("%4d ",n);
            cnt--;
        }

        /* Test the next odd number */
        n+=2;
    }

    puts("");

    return 0;
}

上面的代码(作为“指示” @Chqrlie)避免了平方根,并计算了前1000个素数(正如您期望的那样)。