完美数字错误?
目前我有这段代码,并且它有效。
#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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
函数
isPerfect
中的变量sum
未初始化。Variable
sum
in functionisPerfect
is not initialized.该代码有两个问题,第一个问题是
sum
未初始化,并且通常会设置为调用函数时堆栈上发生的任何垃圾。自动变量不保证初始化为零(或任何其他值),因此,如果您需要它们以特定值开始,您必须自己初始化它们。第二个问题(现已通过您的编辑修复)是缺少
isFactor
。尽管您可能希望将其作为函数,但以下代码可以工作,生成两个小于 100 的完美数字:6
和28
:并且,研究一下它为什么可以工作有了额外的
printf
,这是一个可行的解释。调用函数时,只需减少堆栈指针即可在堆栈上分配局部变量。你的 isPerfect 汇编代码可能只有这样的序言:
然后你使用 %esp 处的内存作为计数器,使用 %esp + 4 来求和。在不初始化
sum
的情况下,它会从该内存位置发生的任何事情开始,该位置可能不为零。现在考虑一下当您首先调用
printf
时会发生什么。毫无疑问,它有自己的局部变量,因此它使用堆栈的一部分,您稍后将依赖该部分将其初始化为零。当printf
返回时,它不会将这些内存位置设置回以前的值,它只是增加堆栈指针以跳过它们。然后,当您调用
isPerfect
时,这些内存位置很可能与您调用printf
之前的位置不同,仅仅是因为printf
> 一直将它们用于自己的目的。如果您幸运(或不幸,取决于您的观点),
sum
所在的内存位置甚至可能为零。但这仍然是未定义的行为,您不应该依赖它 - 显式初始化sum
并且您的(立即)问题将会结束。如果这是家庭作业,请随意忽略这一点(事实上,主动忽略它,因为你可能会因抄袭而被抓)。这就是我第一次实现
isPerfect
函数的方法。它不会调用函数来计算因子,因为虽然它们通常相当快,但它们并非没有成本,而且无论如何,这样简单的事情都可以在一行 C 中完成。毫无疑问,它可以做得更快,但投资回报率在达到某一点后很快就会下降。
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
and28
: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:and then you use the memory at %esp for
counter
and%esp + 4
for sum. Without initialisingsum
, 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 theprintf
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 calledprintf
, simply becauseprintf
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 - initialisesum
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.There's no doubt it could be made faster but the return on investment drops away pretty quickly after a certain point.