完美数字错误?

时间:2011-03-01 05:46:00

标签: c debugging math for-loop numbers

目前我有这段代码,而且有效。

#include <stdio.h>

int isFactor(long number1, long number2)
{
  int isitFactor = (number2 % number1 == 0)?1:0;
  return isitFactor;
}

int isPerfect(int number)
{
   int counter;
   int sum;
   for (counter = 1; counter < number; counter++) 
      if (isFactor(counter, number)) 
         sum += counter;
   return (sum == number);
}

int main()
{
   int counter = 1;
   for (counter = 1; counter <= 100; counter++)
   {
      printf("", isPerfect(counter));
      if (isPerfect(counter)) 
         printf("%d\n", counter);
   }
}

但是,如果我在main()中使用printf取出不必要的行,则无法生成任何数字....可能的原因?!

2 个答案:

答案 0 :(得分:12)

函数sum中的变量isPerfect未初始化。

答案 1 :(得分:6)

这个代码有两个问题,第一个问题是sum没有初始化,通常会设置为调用函数时堆栈上发生的垃圾。自动变量保证初始化为零(或任何事情,因此),因此,如果您需要它们以特定值开头,则必须自己初始化它们。

第二个问题(现在已修复了您的编辑)是缺少isFactor。虽然您可能希望它作为一个函数,但以下代码可以正常工作,产生两个小于100的完美数字628

#include "stdio.h"

#define isFactor(c,n) ((n % c) == 0)

int isPerfect (int number) {
    int counter;
    int sum = 0;  // <-- note initialisation here.
    for (counter = 1; counter < number; counter++)
        if (isFactor(counter, number)) sum += counter;
    return (sum == number);
}

int main (void) {  // try to use one of the two canonical forms.
    int counter = 1;
    for (counter = 1; counter <= 100; counter++)
        if (isPerfect(counter)) printf("%d\n", counter);
    return 0;
}

并且,调查为什么它可以使用额外的printf,这是一个可行的解释。

调用函数时,只需减少堆栈指针即可在堆栈上分配局部变量。你的isPerfect组装代码可能只有一个序言:

sub %esp,8

然后使用%esp中的内存counter%esp + 4来获取总和。如果没有初始化sum,它会从发生在该内存位置的任何内容开始,这可能不是零。

现在想想当你先致电printf时会发生什么。毫无疑问它有自己的局部变量,所以它使用了后来依赖的堆栈部分初始化为零。当printf返回时,它不会将这些内存位置设置回以前的值,它只是递增堆栈指针以跳过它们。

然后,当您致电isPerfect时,很有可能这些记忆位置与您拨打printf之前的记忆位置不同,只是因为printf一直在使用它们它自己的目的。

如果你很幸运(或不幸,取决于你的观点),sum所在的记忆位置甚至可能为零。但是它仍然是未定义的行为,你应该依赖它 - 明确地初始化sum并且你的(直接)问题将会结束。


如果这是作业,请随意忽略这一点(事实上,主动忽略它,因为你可能会因为剽窃而被抓住)。这就是我将isPerfect函数实现为第一次剪切的方法。它并没有调用函数来计算因子,因为它们通常非常快,它们并非没有成本,而且无论如何都可以在单行C中完成。

int isPerfect (int num) {
  int i, left;
  for (i = 1, left = num; i < num; i++)
    if ((num % i) == 0)
      left -= i;
  return (left == 0);
}

毫无疑问,可以加快速度,但投资回报率会在一定程度上迅速下降。