【问题标题】:Non-Prime Number Counter in CC中的非质数计数器
【发布时间】:2017-12-05 19:45:39
【问题描述】:

我想编写一个程序,将 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;
        }
    }
}

【问题讨论】:

  • 使用调试器并单步执行您的程序。
  • 鉴于在第一次循环迭代i == 4 中,您增加了counter,因此counter 永远不会再次0,您只是用@987654327 的连续值填充arr @.

标签: c algorithm primes


【解决方案1】:

发生这种情况是因为您的代码中的逻辑。在你的 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]) 将没有价值...但是当 I=6 时,arr[i-4] 将有一个价值。您可能希望更改此逻辑以计算到目前为止您找到了多少个合数并将找到的数字添加到该点的数组中。

【讨论】:

    【解决方案2】:

    正如@DavidHoelzer 指出的那样,您的代码的问题显然不是重置counter。但是还有另一个错误,因为简单地修复 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。如果您正在寻找合数,请将它们排除在外。如果您要查找非质数,请将它们包括在内。

    【讨论】:

      【解决方案3】:

      复合数是大于 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。 现在,我们可以简单地迭代 throw 它并获得合数。

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

      标准输出的前 10 个数字: 4 6 8 9 10 12 14 15 16 18 20 21 22 24 25 26 27 ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-17
        • 2017-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多