我现在一直在研究这段简单的代码1.5小时,但没有发现错误。我开始疯了;)
你们这些有着清新头脑和观点的人能给我一点暗示,我可能会犯错吗? (我对C来说比较新)
问题是:代码适用于我输入和测试的大多数数字,但我偶然发现了一个不起作用的数字:3486118(或55777888,它是它的倍数)它适用于第一个循环(s),但在因素2之后,它变成了无限循环。
这是我的代码:(非常感谢任何帮助)
// Program calculates prime factors of entered number and returns them
#include <stdio.h>
int main() {
long int num, num_cp;
long int product=1;
/*prime number array up to 100.000*/
long int prime[] = {2, 3, **[...cut out MANY numbers...]** 99971, 99989, 99991};
printf("Please enter a positive integer:\n");
scanf("%li", &num);//55777888 or 3486118 not working... why?
//copy the entered number to keep the original for comparison with "product" and "break;" if equal
num_cp=num;
printf("prime factorization of %li:\n\n", num);
for (int i=0; i<sizeof(prime); i++) {
if (num_cp%prime[i]==0) {
num_cp/=prime[i];
product*=prime[i];
if (product==num) {
printf("%li\n\n", prime[i]);
break;
}
printf("%li*", prime[i]);
//If prime factor found but "product" is still not equal to "num" reset loop counter "i" to -1 (==0 in next loop)
i=-1;
}
}
printf("END");
return 0;
}
答案 0 :(得分:5)
“我现在一直在研究这段简单的代码1.5小时,但没有发现错误。我开始发疯了;)”
别。别管它。走开去吃披萨。在你最喜欢的电影面前出来。洗个澡。瞄准2048年(或其他)的新高分。你的大脑卡在车辙中,你不再看到你的代码了。你只看到你认为你的代码是什么。
当你的大脑离开车辙时,那么 - 只有这样 - 回去并实际阅读你写的代码。不是您认为编写的代码,而是您实际编写的代码。是的,他们是不同的。
答案 1 :(得分:1)
55777888的主要因素是2·2·2·2·2·1743059,其中最后一个因素太大而无法包含在您的列表中。
您可以在代码中修复此问题:当产品等于您找到的素数因子的乘积时,num_cp
为1.如果num_cp
大于1后用尽了主要列表,它是num
的因子。如果num/num_cp
小于您检查过的最大素数,则可以假设num_cp
的剩余值为素数。如果不是,你早先发现了更多的因素。
您可以通过在主循环后添加额外的检查来解决此问题:
if (num_cp > 1) printf("%li\n\n", num_cp);
(如果long int
是您系统上的64位数字,那么您仍然不安全:其余因素可能由数组中不存在的多个数字组成。)
最后:重置for
循环计数器以使循环重新开始并不是一个好主意。它始终从头开始并重新检查您已检查的素数。它只是不自然的程序流程,这使得它很难阅读。在我看来,while
循环而不是内部if
块会更自然。
修改:举例说明:
#include <stdio.h>
int main() {
long int num;
/* prime number array up to 100.000 */
long int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int nprime = sizeof(prime) / sizeof(*prime);
num = 55;
printf("%li == ", num);
for (int i = 0; i < nprime; i++) {
long int p = prime[i];
if (num <= 1) break;
while (num % p == 0) {
num /= prime[i];
printf("%li", p);
if (num > 1) printf(" * ");
}
}
if (num > 1) printf("%li", num);
printf("\n");
return 0;
}
注意事项:
i
循环而不是重置主循环计数器while
,这会消耗相同因子的所有重复。如果素数p
没有除数,则不会输入while
循环,就像if
子句一样。num
的副本,并在整个过程中使用了num
,主要是为了消除混乱。我还删除了product
。你所有主要因素应该乘以原始数字的逻辑是好的。但它也是相反的:在将数字除以所有素数之后,我们留下1.我们必须将数字除以。通过删除产品,我们只需跟踪一个变量而不是两个变量。break
条件移至前方,因此我们会及时收到负数和0。那就是说,你的代码方式并没有错,只是在某些地方可能有点不寻常。