Если использовать <или <= в цикле for

Если вам нужно было проходить через цикл 7 раз, вы бы использовали:

for (int i = 0; i < 7; i++)

или

for (int i = 0; i <= 6; i++)

Существует два соображения:

  • производительности
  • читаемость

Для производительности я предполагаю Java или С#. Имеет ли значение, если используется "меньше" или "меньше или равно"? Если у вас есть понимание на другом языке, укажите, пожалуйста.

Для удобства чтения я принимаю массивы на основе 0.

UPD: Мое упоминание о массивах на основе 0 может смутить. Я не говорю об итерации через элементы массива. Просто общий цикл.

Существует хорошая точка ниже об использовании константы, на которой объясняется, что это за волшебное число. Поэтому, если бы у меня было "int NUMBER_OF_THINGS = 7", тогда "i <= NUMBER_OF_THINGS - 1" выглядело бы странно, не так ли.

Ответ 1

Первым является idiomatic. В частности, он указывает (в смысле 0) количество итераций. При использовании чего-то на основе 1 (например, JDBC, IIRC) у меня может возникнуть соблазн использовать < =. Итак:

for (int i=0; i < count; i++) // For 0-based APIs

for (int i=1; i <= count; i++) // For 1-based APIs

Я бы ожидал, что разница в производительности будет незначительно мала в реальном коде.

Ответ 2

Оба эти цикла повторяются 7 раз. Я бы сказал, что тот, у кого есть 7, более читабельный/понятный, если у вас нет веской причины для другого.

Ответ 3

Я помню из своих дней, когда мы собрали 8086 в колледже, это было более результативно:

for (int i = 6; i > -1; i--)

поскольку была операция JNS, которая означает Jump, если No Sign. Использование этого означало, что после каждого цикла не было поиска в памяти, чтобы получить сравнительное значение и не сравнивать. В наши дни большинство компиляторов оптимизируют использование регистров, поэтому память больше не важна, но вы все равно получаете не требуемое сравнение.

Кстати говоря, 7 или 6 в вашем цикле вводит " магический номер". Для лучшей читаемости вы должны использовать константу с именем раскрытия намерения. Вот так:

const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)

EDIT: люди arent получают сборку, поэтому требуется более полный пример:

Если мы делаем для (i = 0; я <= 10; я ++), вы должны сделать это:

    mov esi, 0
loopStartLabel:
                ; Do some stuff
    inc esi
                ; Note cmp command on next line
    cmp esi, 10
    jle exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

Если мы делаем для (int я = 10; i > -1; i--), то вы можете уйти от этого:

    mov esi, 10
loopStartLabel:
                ; Do some stuff
    dec esi
                ; Note no cmp command on next line
    jns exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

Я только что проверил, и компилятор Microsoft С++ не выполняет эту оптимизацию, но если это так:

for (int i = 10; i >= 0; i--) 

Так морально, если вы используете Microsoft С++ †, а восходящий или нисходящий не имеет значения, чтобы получить быстрый цикл, который вы должны использовать:

for (int i = 10; i >= 0; i--)

а не любой из них:

for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)

Но откровенно получение удобочитаемости "for (int я = 0; я <= 10; я ++)" обычно гораздо важнее, чем отсутствие одной команды процессора.

† Другие компиляторы могут делать разные вещи.

Ответ 4

Я всегда использую < array.length, потому что легче читать, чем <= array.length-1.

также имеющий < 7 и учитывая, что вы знаете, что он начинается с индекса 0, он должен быть интуитивным, чтобы число было числом итераций.

Ответ 5

С оптимизированной точки зрения это не имеет значения.

С точки зрения стиля кода я предпочитаю <, Причина:

for ( int i = 0; i < array.size(); i++ )

настолько читабельнее, чем

for ( int i = 0; i <= array.size() -1; i++ )

также < дает вам сразу несколько итераций.

Еще одно голосование за < заключается в том, что вы можете предотвратить множество случайных ошибок "один за другим".

Ответ 6

@Chris. Ваше утверждение о том, что длина .Length является дорогостоящей в .NET, на самом деле неверна, а в случае простых типов - полная противоположность.

int len = somearray.Length;
for(i = 0; i < len; i++)
{
  somearray[i].something();
}

на самом деле медленнее, чем

for(i = 0; i < somearray.Length; i++)
{
  somearray[i].something();
}

Позднее это случай, который оптимизируется во время выполнения. Поскольку среда выполнения может гарантировать, что я является допустимым индексом в массиве, проверки границ не выполняются. В первом случае время выполнения не может гарантировать, что я не был изменен до цикла и принудительно проверяет границы массива для каждого поиска индекса.

Ответ 7

Это не влияет на производительность. Поэтому я бы использовал то, что легче понять в контексте проблемы, которую вы решаете.

Ответ 8

Я предпочитаю:

for (int i = 0; i < 7; i++)

Я думаю, что более легко переводить "через семь циклов".

Я не уверен в производительности - я подозреваю, что любые различия будут скомпилированы.

Ответ 9

В Java 1.5 вы можете просто сделать

for (int i: myArray) {
    ...
}

поэтому для случая массива вам не нужно беспокоиться.

Ответ 10

Я не думаю, что есть разница в производительности. Вторая форма, безусловно, более читаема, хотя вам не нужно мысленно вычитать ее, чтобы найти последний номер итерации.

EDIT: Я вижу, что другие не согласны. Для меня лично мне нравится видеть фактические номера индексов в структуре цикла. Может быть, потому, что это больше напоминает синтаксис Perl 0..6, который, как я знаю, эквивалентен (0,1,2,3,4,5,6). Если я вижу 7, мне нужно проверить рядом с ним оператор, чтобы убедиться, что на самом деле индекс 7 никогда не был достигнут.

Ответ 11

Я бы сказал, что используйте версию "7", потому что это то, что читают большинство людей, поэтому, если люди читают ваш код без сбоев, они могут ошибочно интерпретировать его.

Я бы не стал беспокоиться о том, быстрее, чем "< =", просто читайте.

Если вы хотите перейти на увеличение скорости, рассмотрите следующее:

for (int i = 0; i < this->GetCount(); i++)
{
  // Do something
}

Чтобы увеличить производительность, вы можете немного изменить ее на:

const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
  // Do something
}

Обратите внимание на удаление GetCount() из цикла (потому что это будет запрошено в каждом цикле) и смена "i ++" на "++ i".

Ответ 12

В С++ я предпочитаю использовать !=, который можно использовать со всеми контейнерами STL. Не все итераторы контейнеров STL менее сопоставимы.

Ответ 13

Edsger Dijkstra написал статью об этом в 1982 году, где он утверждает, что нижний <= я < верхняя:

Существует наименьшее натуральное число. Исключение нижней границы - в b) и d) - силы для подпоследовательности, начиная с наименьшего натурального числа, нижней границы, указанной в области неестественных чисел. Это уродливо, поэтому для нижней границы мы предпочитаем ≤, как в а) и в). Рассмотрим теперь подпоследовательности, начиная с наименьшего натурального числа: включение верхней границы затем заставит последнее быть неестественным к тому времени, когда последовательность уменьшится до пустой. Это уродливо, поэтому для верхней границы мы предпочитаем < как в пунктах а) и d). Мы заключаем, что соглашение а) должно быть предпочтительным.

Ответ 14

Во-первых, не используйте 6 или 7.

Лучше использовать:

int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){

}

В этом случае это лучше, чем использование

for (int day = 0; day <= numberOfDays  - 1; day++){

}

Еще лучше (Java/С#):

for(int day = 0; day < dayArray.Length; i++){

}

И еще лучше (С#)

foreach (int day in days){// day : days in Java

}

Реверсивный цикл действительно быстрее, но, поскольку он труднее читать (если не вами другими программистами), лучше его избегать. Особенно в С#, Java...

Ответ 15

Я согласен с толпой, говорящей, что 7 имеет смысл в этом случае, но я бы добавил, что в случае, когда значение 6 важно, скажите, что вы хотите уточнить, что вы действуете только на объекты до 6-го индекса, тогда <= лучше, так как это облегчает просмотр.

Ответ 16

Вернувшись в колледж, я помню что-то об этих двух операциях, похожих на время вычисления на процессоре. Конечно, мы говорим на уровне сборки.

Однако, если вы говорите на С# или Java, я действительно не думаю, что это будет ускорение скорости по сравнению с другим. Несколько наносекунд, которые вы получаете, скорее всего, не будут стоить каких-либо путаниц, которые вы вводите.

Лично я бы написал код, который имеет смысл с точки зрения бизнес-реализации, и убедитесь, что он легко читается.

Ответ 17

Как небольшая сторона, когда вы перебираете массив или другую коллекцию в .Net, я нахожу

foreach (string item in myarray)
{
    System.Console.WriteLine(item);
}

чтобы быть более читаемым, чем числовой цикл. Это, конечно, предполагает, что фактический счетчик Int сам не используется в коде цикла. Я не знаю, есть ли изменение производительности.

Ответ 18

Это подпадает под категорию Неправильный код неправильного кода.

В нумерованных языках индексирования, таких как Java или С#, люди привыкли к изменениям в index < count. Таким образом, использование этого соглашения о дефакто может сделать очевидные ошибки.

Что касается производительности: любой хороший компилятор, стоящий на его памяти, должен отображаться как не проблема.

Ответ 19

Есть много веских причин для написания я < 7. Наличие числа 7 в цикле, который итерации 7 раз, является хорошим. Производительность фактически идентична. Почти каждый пишет я < 7. Если вы пишете для удобства чтения, используйте форму, которую каждый узнает сразу.

Ответ 20

Я всегда предпочитал:

for ( int count = 7 ; count > 0 ; -- count )

Ответ 21

Вместо этого вы можете использовать !=. Таким образом, вы получите бесконечный цикл, если вы сделаете ошибку при инициализации, заставляя ошибку замечать раньше и любые проблемы, которые она вызывает, чтобы ограничить возможность застревания в цикле (вместо того, чтобы иметь проблему намного позже и не находить она).

Ответ 22

Создание привычки использовать < сделает его согласованным как для вас, так и для читателя, когда вы выполняете итерацию через массив. Для всех будет проще иметь стандартную конвенцию. И если вы используете язык с массивами на основе 0, то < это соглашение.

Это почти наверняка имеет значение больше, чем любая разница в производительности между < и < =. Сначала оцените функциональность и читаемость, затем оптимизируйте.

Еще одно замечание: лучше иметь привычку делать ++ i, а не я ++, так как выборка и приращение требуют временного и приращения, а выборки - нет. Для целых чисел ваш компилятор, вероятно, будет оптимизировать временное прохождение, но если ваш итерирующий тип более сложный, он, возможно, не сможет.

Ответ 23

Не используйте магические числа.

Почему это 7? (или 6 в этом отношении).

используйте правильный символ для номера, который вы хотите использовать...

В этом случае я думаю, что лучше использовать

for ( int i = 0; i < array.size(); i++ )

Ответ 24

"< и '< =' - это точно такая же производительность.

"< оператор является стандартным и более легким для чтения в цикле с нулевой точкой.

Использование ++ я вместо я ++ повышает производительность на С++, но не на С# - я не знаю о Java.

Ответ 25

Как наблюдали люди, нет никакой разницы ни в одной из двух упомянутых вами альтернатив. Чтобы подтвердить это, я сделал несколько простых тестов в JavaScript.

Здесь вы можете увидеть результаты здесь. Из этого ясно, что если я поменяю позицию 1-го и 2-го тестов, результаты для этих двух тестов своп, это явно проблема с памятью. Однако 3-й тест, в котором я меняю порядок итерации, явно быстрее.

Ответ 26

Как говорят все, принято использовать итераторы с индексом 0, даже для вещей вне массивов. Если все начинается с 0 и заканчивается на n-1, а нижние границы всегда <=, а верхние границы всегда <, там гораздо меньше думать о том, что вам нужно делать при просмотре кода.

Ответ 27

Отличный вопрос. Мой ответ: используйте тип A ('<')

  • Вы ясно видите, сколько итераций у вас есть (7).
  • Разница между двумя конечными точками - это ширина диапазона
  • Меньше символов делает его более читаемым
  • Вы чаще всего имеете общее количество элементов i < strlen(s), а не индекс последнего элемента, поэтому важно иметь однородность.

Другая проблема заключается в всей этой конструкции. i появляется 3 раза, поэтому это может быть неправильно. Конструкция for-loop говорит , как сделать вместо , что делать. Я предлагаю принять это:

BOOST_FOREACH(i, IntegerInterval(0,7))

Это более понятно, компилируется для того, чтобы exaclty использовать те же инструкции asm и т.д. Попросите меня ввести код IntegerInterval, если хотите.

Ответ 28

Так много ответов... но я считаю, что есть что добавить.

Мое предпочтение заключается в том, чтобы буквальные числа четко отображали , какие значения "i" будут принимать в цикле. Таким образом, в случае итерации с использованием массива с нулевым значением:

for (int i = 0; i <= array.Length - 1; ++i)

И если вы просто зацикливаете, а не итерируете через массив, считая от 1 до 7, это довольно интуитивно понятно:

for (int i = 1; i <= 7; ++i)

Производительность коучинга удобочитаемости до тех пор, пока вы его не профилируете, так как вы, вероятно, не знаете, что компилятор или время выполнения будут делать с вашим кодом до тех пор.

Ответ 29

Я думаю, что все в порядке, но когда вы выбрали, придерживайтесь того или другого. Если вы привыкли использовать < =, то постарайтесь не использовать < и наоборот.

Я предпочитаю < =, но в ситуациях, когда вы работаете с индексами, начинающимися с нуля, я, вероятно, попытаюсь использовать <. Все это личное предпочтение.

Ответ 30

Строго с логической точки зрения, вы должны думать, что < count будет более эффективным, чем <= count по той причине, что <= будет тестировать и на равенство.