Если использовать <или <= в цикле 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" выглядело бы странно, не так ли.

+119
источник поделиться
39 ответов
  • 1
  • 2

Первым является 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

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

+279
источник

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

+71
источник

Я помню из своих дней, когда мы собрали 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; я ++)" обычно гораздо важнее, чем отсутствие одной команды процессора.

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

+54
источник

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

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

+26
источник

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

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

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

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

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

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

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

+17
источник

@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();
}

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

+9
источник

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

+5
источник

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

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

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

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

+5
источник

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

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

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

+4
источник

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

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

+4
источник

Я бы сказал, что используйте версию "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".

+4
источник

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

+4
источник

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

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

+4
источник

Во-первых, не используйте 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...

+3
источник

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

+2
источник

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

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

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

+2
источник

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

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

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

+2
источник

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

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

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

+2
источник

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

+1
источник

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

for ( int count = 7 ; count > 0 ; -- count )
+1
источник

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

+1
источник

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

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

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

+1
источник

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

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

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

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

for ( int i = 0; i < array.size(); i++ )
+1
источник

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

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

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

+1
источник

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

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

+1
источник

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

+1
источник

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

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

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

BOOST_FOREACH(i, IntegerInterval(0,7))

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

+1
источник

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

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

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

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

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

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

+1
источник

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

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

0
источник

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

0
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос