作为前言,我使用的是 Visual Studio 2022。Project Euler 上的问题指出:
如果我们列出 10 以下的所有自然数 是 3 的倍数 或 5,我们得到 3、5、6 和 9。这些倍数的总和是 23。求 1000 的所有倍数的总和 或者 下面。
几个小时后我自己完成了代码的大部分调试,但无法弄清楚这个小事情。我还问了一位自己解决了这个问题的朋友,在与她自己的工作代码进行比较后,她很困惑为什么它不正确。
这是我的代码:
int x = 0, y = 0, totalSum = 0;
//multiples of 3
for (int i = 0; x < 1000; i++)
{
x = 3 * i;
if (x % 5 != 0)
{
totalSum += x;
Console.WriteLine(totalSum);
}
}
//multiples of 5
for (int n = 0; y < 1000; n++)
{
y = 5 * n;
totalSum += y;
Console.WriteLine(totalSum);
}
Console.WriteLine(totalSum);
Console.ReadKey();
运行时,控制台输出235,170。我揪着头发查了一下正确答案,我知道答案是233,168。我只是不知道如何到达那里。奇怪的是,当我将顶部
for
循环更改为 . 。 .
for (int i = 0; x < 996; i++)
{
x = 3 * i;
if (x % 5 != 0)
{
totalSum += x;
Console.WriteLine(totalSum);
}
}
。 。 。它输出 233,169。一关。我对发生的事情感到非常困惑。我对编程非常陌生——只在这里那里做了大约一个月,所以如果我的代码不是最优的,我深表歉意。感谢您的帮助,提前致谢!
首先恭喜你:用mod抓到15个案例干得好(
%
)!错误不在这里。
我相信错误在于
for (int i = 0; x < 1000; i++)
和
for (int n = 0; y < 1000; n++)
线。
你看,你可以想到 for 循环的形式
for(variable declaration; condition check; variable change) {
body();
}
如
variable declaration;
while(condition check) {
body();
variable change;
}
在代码中,您使用
i
和 n
作为变量来跟踪迭代,但可以这么说,使用 x
和 y
作为 condition check
。这会导致这些循环再次运行。为什么?
问题是,考虑最后几个测试用例...... for 循环求和 3 秒何时停止?你会想到 999,因为 1002 大于 1000。然而,之后
Console.WriteLine(totalSum);
行,变量
i
将增加到334...但不会停止循环,因为x
的值仍然是999
。因此下面的body()
将再次运行,i
将增加到335,然后循环将停止为1002 > 1000
。
注意:您可能可以通过查看其中某处的
来捕获此错误。此问题通常称为“差一错误”。一般来说,需要通过打印或其他方式(也许在调试器中单步执行?)仔细检查循环的开始和结束来捕获这些。 虽然您可以在末尾添加另一个 if 语句,并使用类似的检查Console.WriteLine("i: " + i + " x: " + x);
if(x == 999) {
break;
}
这是多余的,并且实际上损害了代码的理解和可重用性。
一般来说,我会告诉您:作为初学者,不要在
condition check
中使用您声明的变量之外的其他变量。这可能会导致像我上面解释的那样的蠕动小错误(
off-by-one错误)。 提示:您可以重构它以使用
i
作为
(也许这里可以使用整数除法?)或condition check
,两者都需要一点重构。 话虽如此,作为一个初学者,我不想把答案告诉你!我希望上述建议,或许还有更多的批评,能够帮助您找到正确的解决方案。x
快乐解决问题!
编辑:我发现由于循环在开始时的检查方式,它会变成一倍。例如。 5199 仍然小于 1000,因此循环继续进行并执行 5
200,超出了我认为设置的限制。我相应地改变了循环。我认为这比实际情况更复杂。感谢您的帮助。