C中的非素数计数器

时间:2017-12-05 19:45:40

标签: c algorithm primes

我想编写一个程序,用于将10.000之前的所有非素数(复合)数存储在数组中。我在下面做了这个算法,但它不起作用。当我打印出应该保存复合数字的数组时,它只是从4到10.000计数。

问题出在哪里?我真的很看,但我看不到。

#include <stdio.h>
#define SIZE 10000

void compositeChecker(int[]);

int main() {
    int k;
    int compositeArray[SIZE]= {0};
    compositeChecker(compositeArray);
    for(k=0; k<100; k++) {
        printf("%d\n",compositeArray[k]);
    }
}

void compositeChecker(int arr[]) {
    int i,j,counter=0;

    for(i=4; i<10000; i++) {
        for(j=2; j<i; j++) {
            if((i%j)==0) {
                counter++;
            }
        }
        if(counter!=0) {
            arr[i-4]=i;
        }
    }
}

3 个答案:

答案 0 :(得分:4)

由于代码中的逻辑,这种情况正在发生。在for循环内部,您可以这样说:

for(j=2;j<i;j++) {
 if((i%j)==0){

    counter++;

 }    
}

if(counter!=0){

    arr[i-4]=i;
}

因此,一旦找到任何复合数字,就会增加计数器。计数器永远不会在循环中重置为零,因此每个数字都会添加到数组中。即使你的逻辑是固定的,你也会以一种没有意义的方式为数组添加值。考虑值5和6。

即使您更正了逻辑,也不会添加5 ...所以arr[i-4](arr [1])没有价值......但是当我= 6时,arr[i-4]会有一个值。您可能希望更改此逻辑以计算到目前为止找到的复合数量,并在此时添加找到的数字。

答案 1 :(得分:0)

代码问题显然没有重置counter,因为@DavidHoelzer指出了这一点。但是还有另一个错误,就是简单地修复counter会在你的输出中留下零点。

我认为真正的解决方法是消除counter,因为它是错误的。一旦确定一个数字是复合的,你就会继续检查更多的除数,但在测试if (counter != 0)时忽略所有额外的工作。所以,一旦我们找到第一个除数并进入下一个数,我们就应该做一个注释。这是对break语句的完美使用:

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

#define SIZE 100

void compositeChecker(bool array[]) {

    for (int i = 3; i < SIZE; i++) {
        for (int j = 2; j < i; j++) {
            if (i % j == 0) {
                array[i] = true;
                break;
            }
        }
    }
}

int main() {

    bool compositeArray[SIZE] = {false};

    compositeChecker(compositeArray);

    for (int k = 0; k < SIZE; k++) {
        if (compositeArray[k]) {
                printf("%d\n", k);
        }
    }
}

请注意,我还更改了compositeArray不是复合数字列表,而是更改了一个布尔值列表,表明特定索引是否是复合索引。

最后一个问题是术语之一。您的代码正在寻找 复合 数字,但您的标题和文字说明 非素数 。区别在于您处理0和1的方式。如果您正在寻找复合数字,请将它们排除在外。如果您正在寻找非素数,请加入它们。

答案 2 :(得分:0)

复合数是大于1的非素数。所以你要做的就是找到高达10k的素数。它可以通过红霉素筛轻松完成。

The principle of the sieve of Eratosthenes

创建将数字映射到{1,0},1的数组 - 如果数字是素数,0 - 如果是复合数。

#define SIZE 10001
int is_prime[10000];

现在让我们初步筛选:

void init_sieve()
{
    int i, j;
    for( i = 0; i < SIZE; ++i )
        is_prime[i] = 1;

    is_prime[0] = is_prime[1] = 0;

    for( i = 2; i < SIZE; ++i )
        if( is_prime[i] )
            for( j = i*i; j < SIZE; j += i )
                is_prime[j] = 0;
}

所以我们得到了bool数组,如果元素的索引为素数,则每个元素为1,否则为0。 现在,我们可以简单地迭代抛出它并获得复合数字。

for( int i = 4; i < SIZE; ++i )
    if( !is_prime[i] )
    {
        printf( "%d\n", i );
    }

来自stdout的前10个号码:     4     6     8     9     10     12     14     15     16     18     20     21     22     24     25     26     27     ...