请告诉我为什么这个C#for循环执行后的和的值是20而不是30:
for (int i = 2; i < 10; i += 2)
{
sum += i;
}
在我看来,在第一次迭代结束时,我将是2和总和2,在第二次结束时我将是4并且总和6,然后是6和12,然后是8和20.然后,当循环开始进入第5次迭代时,我仍然会在8时小于10,所以我会增加到10并且sum将是20 + 10 = 30.然后下一次i = 10,所以执行停止。但答案是20.为什么循环不进入第5次迭代?请对我温柔。
非常感谢您的启发。
答案 0 :(得分:11)
当4 times
为i
且2, 4, 6,
时,循环执行8
总计是20。
这里没有什么可以解决的谜。当i
达到10
时,for条件i < 10
的评估为false,因此,10永远不会添加到sum
变量
要完成答案,for
statement的逻辑很简单:
(i=2)
(i < 10)
{ ... whatever... }
(i+=2)
答案 1 :(得分:2)
Loop 0 : i = 2, sum = 0 + 2 = 2
Loop 1 : i = 2 + 2 = 4, sum = 2 + 4 = 6
Loop 2 : i = 4 + 2 = 6, sum = 6 + 6 = 12
Loop 3 : i = 6 + 2 = 8, sum = 12 + 8 = 20
Loop 4 : i = 8 + 2 = 10, for loop stops.
Result: sum = 20
你写的for循环与:
相同int i = 2;
while(true)
{
if (i < 10)
{
sum += i;
}
else break;
i += 2;
}
所以i
递增然后进行评估,如果它不符合条件,则循环将被破坏。
答案 2 :(得分:1)
在for (a;b;c) d;
中,评估顺序是a,b,d,(c,b,d)其中(c,b,d)重复(如果b
是false
,循环在那里破裂)。你似乎认为顺序是(b,c,d)。单步执行调试器中的代码将使此清楚。
在您的情况下,这意味着在i == 8
之后,i
会增加到10
,然后会对i < 10
进行测试;由于它是false
,因此在将10
添加到sum
之前,循环会中断。对于for
循环来说,这是一种更简单自然的方式,尤其是在循环数组的情况下:
// actual; i will have values from 0 (inclusive) to array.Length (exclusive)
for (int i = 0; i < array.Length; i++)
// if it worked how you assumed, it'd be
for (int i = 0; i < array.Length - 1; i++)
// but the last time you go through the loop, i < array.Length - 1 isn't true
答案 3 :(得分:0)
您似乎对for
的运作方式存在误解。我将循环转换为执行的语句,因此您可以获得更好的想法:
int i = 2;
if (i < 10) {
sum += i; // sum = 2
}
i += 2; // i = 4
if (i < 10) {
sum += i; // sum = 6
}
i += 2; // i = 6
if (i < 10) {
sum += i; // sum = 12
}
i += 2; // i = 8
if (i < 10) {
sum += i; // sum = 20
}
i += 2; // i = 10
if (i < 10) {
// nothing, since 10 <= 10, but *not* 10 < 10
}
答案 4 :(得分:0)
正如其他人已经指出的那样,答案是循环没有进入第5次迭代,因为你的例子中的[stop-]条件是'&lt;' (小于运算符)并且不是'&lt; ='(小于或等于)以便循环的数量,其可以被定义为'2n&lt; 10'解析为'n&lt; 5',其中4是n的最接近的有效匹配。
您可能会发现the MS docs about it有帮助。这是一段摘录:
for(initializer; condition; iterator)
body
初始化部分设置初始条件。在进入循环之前,本节中的语句只运行一次。该部分只能包含以下两个选项之一。
本地循环变量的声明和初始化,如第一个示例所示(int i = 1)。该变量是循环的局部变量,无法从循环外部访问。
零个或多个语句表达[...]
条件部分包含一个布尔表达式,该表达式经过评估以确定循环是应该退出还是应该再次运行。
迭代器部分定义了循环体的每次迭代后发生的事情。迭代器部分包含零个或多个[...]语句表达式,以逗号[...]
分隔
作为旁注,可能值得一提的是关系测试的运算符,如'&lt;'并且'&lt; ='可能会因用户定义的类型而重载并使循环难以读取,但由于您使用int作为控件变量类型(不是用户定义的类型),因此您的情况并非如此示例
C# language specification - ECMA-334在“12.3.3.9 For语句”中显示了一个非常明确的定义,它也解释了for循环
for (int i = 2; i < 10; i += 2)
{
sum += i;
}
可以转换为while循环
int sum = 0;
int i = 2;
while (i < 10)
{
sum += i;
i += 2;
}
使指令的顺序更加明显。
使用ildasm,除了一些NOP指令外,两个循环的输出是相同的。这是一个带注释的小版本:
.method private hidebysig static void Testloop() cil managed
{
// Code size 27 (0x1b)
.maxstack 2
.locals init ([0] int32 sum, <-- this is location 0 --> 1. int sum = 0;
[1] int32 i, <-- this is location 1 --> 2. int i = 2;
[2] bool CS$4$0000) <-- this is location 2 --> 3. unnamed temporary result storage for the i < 10 comparison
IL_0000: nop --> no operation is the machine code equivalent of a space character and can be ignored
IL_0001: ldc.i4.0 --> 1. int sum = 0;
IL_0002: stloc.0 --> 1.
IL_0003: ldc.i4.2 --> 2. int i = 2;
IL_0004: stloc.1 --> 2.
IL_0005: br.s IL_0011 --> branch to target IL_0011, which is a "goto" and jumps over the conditional check and iterator code which starts at IL_0007
IL_0007: nop --> no operation is the machine code equivalent of a space character and can be ignored
IL_0008: ldloc.0 --> 5. sum += i
IL_0009: ldloc.1 --> 5.
IL_000a: add --> 5.
IL_000b: stloc.0 --> 5.
IL_000c: nop --> no operation is the machine code equivalent of a space character and can be ignored
IL_000d: ldloc.1 --> 6. i += 2
IL_000e: ldc.i4.2 --> 6.
IL_000f: add --> 6.
IL_0010: stloc.1 --> 6.
IL_0011: ldloc.1 --> 3. i < 10
IL_0012: ldc.i4.s 10 --> 3.
IL_0014: clt --> 3.
IL_0016: stloc.2 --> 4. continue until ( 3. ) is true (meaning, i >= 10) by jumping back to the start at IL_0007
IL_0017: ldloc.2 --> 4.
IL_0018: brtrue.s IL_0007 --> 4.
IL_001a: ret --> the closing bracket of the method Testloop()
} // end of method Program::Testloop