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