完美数字错误?

发布于 2024-10-19 16:36:25 字数 657 浏览 2 评论 0原文

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

#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 删除不必要的行,它就无法产生任何数字......可能的原因?!

Currently I have this code, and it works.

#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);
   }
}

However, if I take out the unnecessary line with the printf in main(), it fails to produce any numbers.... Possible causes?!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹂绝世的画 2024-10-26 16:36:25

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

Variable sum in function isPerfect is not initialized.

同展鸳鸯锦 2024-10-26 16:36:25

该代码有两个问题,第一个问题是 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 处的内存作为计数器,使用 %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);
}

毫无疑问,它可以做得更快,但投资回报率在达到某一点后很快就会下降。

You had two problems with that code, the first is that sum is not initialised and will generally be set to whatever rubbish happened to be on the stack at the time the function was called. Automatic variables are not guaranteed to be initialised to zero (or anything, for that matter) so, if you need them to start with a specific value, you have to initialise them yourself.

The second problem (now fixed with your edit) was that isFactor is missing. Although you probably want it as a function, the following code works, producing the two perfect numbers less than 100, 6 and 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;
}

And, looking into why it might be working with that extra printf, here's a viable explanation.

When calling a function, the local variables are allocated on the stack simply by reducing the stack pointer. Your isPerfect asembly code probably just has a prolog like:

sub %esp,8

and then you use the memory at %esp for counter and %esp + 4 for sum. Without initialising sum, it starts with whatever happened to be at that memory location, which is probably not zero.

Now think about what happens when you call printf first. It no doubt has its own local variables so it uses the part of the stack that you will later be relying on to be initialised to zero. When the printf returns, it doesn't set those memory locations back to their previous values, it just increments the stack pointer to skip over them.

Then, when you call isPerfect, there's a good chance that those memory locations will be different to what they were before you called printf, simply because printf has been using them for its own purposes.

If you're lucky (or unlucky, depending on your viewpoint), the memory location where sum will be may even be zero. But it's undefined behaviour nonetheless and you should not rely on it - initialise sum explicitly and your (immediate) problems will be over.


If this is homework, feel free to ignore this bit (in fact, actively ignore it since you may get caught out for plagiarism). This is how I would implement the isPerfect function as a first cut. It doesn't call functions to work out factors since, while they're generally quite fast, they're not without cost, and something that simple can be done in a single line of C anyway.

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

There's no doubt it could be made faster but the return on investment drops away pretty quickly after a certain point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文