完美数字错误?

tek*_*agi 1 c math debugging 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);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

cod*_*ict 12

sum函数变量isPerfect未初始化.


pax*_*blo 6

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

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

而且,调查为什么它可能会与额外的工作printf,这是一个可行的解释.

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

sub %esp,8
Run Code Online (Sandbox Code Playgroud)

然后你使用%esp的内存counter%esp + 4sum.如果没有初始化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);
}
Run Code Online (Sandbox Code Playgroud)

毫无疑问,它可以加快速度,但投资回报在一定程度上会很快消失.