2013-12-11 2 views
-1

Скажите, пожалуйста, почему значение суммы после этого C# для цикла выполняет это 20, а не 30:Когда выражение инкремента выполнить

for (int i = 2; i < 10; i += 2) 
{ 
    sum += i; 
} 

Мне кажется, что в конце первой итерации, я будет 2 и сумма 2, в конце второго i будет 4 и сумма 6, затем 6 и 12, затем 8 и 20. Затем, когда цикл начинается с 5-й итерацией, я все равно будет меньше 10 при 8, поэтому я увеличил бы до 10, и сумма будет равна 20 + 10 = 30. Тогда в следующий раз вокруг i = 10, поэтому выполнение прекратится. Но ответ 20. Почему петля не входит в эту 5-ю итерацию? Пожалуйста, будьте осторожны со мной.

Большое спасибо за просвещение.

+1

Вы должны были бы я <= 10, чтобы получить то, что вы ожидаете –

+18

Хорошая возможность узнать, как работает отладчик :) – JMK

+0

Этот вопрос, как представляется, не по теме, потому что просят нас ececute предоставленный код, чтобы получить ответ. Вот для чего нужны компилятор и отладчик. – rene

ответ

11

Цикл выполняется 4 times, когда i является 2, 4, 6, и 8
Всего 20.

Нет мистерия решить здесь. Когда i достигает 10 оценки из за состояния i < 10 является ложным и, таким образом, 10 никогда не добавляется к sum переменной

Чтобы завершить ответ логика for statement проста:

  • Установить начальное значение для переменный, которая контролирует экспрессию выхода (i=2)
  • вычисляет выражение выхода, если верно ввести для тела, если ложного выход (i < 10)
  • Выполните для тела { ... whatever... }
  • Increment переменная для шагов требуется (i+=2)
  • Restart из оценки выражения выхода
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 

для цикла Вы писали так же, как:

int i = 2; 
while(true) 
{ 
    if (i < 10) 
    { 
     sum += i; 
    } 
    else break; 

    i += 2; 
} 

так i увеличивается и затем оценивается, если он не удовлетворяет условию, что цикл будет разбит.

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 
} 
1

В for (a;b;c) d; порядок оценки является, б, д, (с, б, г), где (с, Ь , 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 
0

Как и другие уже указывали, ответ в том, что цикл не входит в 5-й итерации потому что условие [stop-] в вашем примере - «<» (меньше оператора), а не «< =» (меньше или равно), так что число петель, которое может быть определено как «2n < 10», разрешается 'n < 5', где 4 является ближайшим действительным совпадением для n.

Вы можете найти the MS docs about it полезно. Вот выдержка:

для (инициализатора; условие; итератора)

body 

Раздел инициализатор устанавливает начальные условия. Операторы в этом разделе выполняются только один раз, прежде чем вводить цикл. Раздел может содержать только один из следующих двух вариантов.

  • Объявление и инициализация локальной переменной цикла, как показывает первый пример (int i = 1). Переменная локальна для цикла и не может быть доступна извне цикла.

  • Ноль или более заявление expressons [...]

Раздел условие содержит логическое выражение, которое вычисляется для определения того, следует ли цикл выхода или должен работать снова.

Раздел итератора определяет, что происходит после каждой итерации тела цикла. Раздел итератор содержит ноль или более [...] заявление выражений, разделенных запятыми [...]

в качестве Замечание, возможно, стоит отметить, что операторы реляционной тестирования, как «<» и ' < = 'может быть перегружен для пользовательских типов и сделать цикл более трудным для чтения, но поскольку вы используете int в качестве типа переменных управления (который не является определяемым пользователем типом), это не может быть применимо к вашему примеру.

C# language specification - ECMA-334 показывает очень четкое определение в «12.3.3.9 для операторов», которые также explaines, что цикл

for (int i = 2; i < 10; i += 2) 
{ 
    sum += i; 
} 

может быть переведено в цикл в то время как

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 
Смежные вопросы