Следует использовать
если бы вам пришлось повторить цикл 7 раз, вы бы использовали:
for (int i = 0; i < 7; i++)
или:
for (int i = 0; i <= 6; i++)
есть два соображения:
- производительность
- читабельности
для производительности я предполагаю Java или C#. Имеет ли значение "меньше" или "меньше или равно" используется? Если у вас есть понимание для другого языка, пожалуйста, укажите, какой.
для удобства чтения я предполагаю, что 0-на основе матрицы.
UPD: мое упоминание о массивах на основе 0 может привести к путанице. Я не говорю о переборе элементов массива. Просто общий цикл.
ниже есть хороший момент об использовании константы, которая объяснила бы, что такое это магическое число. Так что если бы я...int NUMBER_OF_THINGS = 7
" то "i <= NUMBER_OF_THINGS - 1
" выглядело бы странно, не было.
30 ответов:
первый более идиоматическое. В частности, он указывает (в смысле 0) количество итераций. При использовании чего-то 1-based (например, JDBC, IIRC) у меня может возникнуть соблазн использовать
for (int i=0; i < count; i++) // For 0-based APIs for (int i=1; i <= count; i++) // For 1-based APIs
Я ожидал бы, что разница в производительности будет незначительно мала в реальном коде.
оба этих цикла повторяются 7 раз. Я бы сказал, что один с 7 в нем более читаем/яснее, если у вас нет действительно веской причины для другого.
Я помню из моих дней, когда мы делали 8086 Ассамблеи в колледже это было более эффективным, чтобы сделать:
for (int i = 6; i > -1; i--)
как было!--10-->JNS операция, которая означает прыжок, если нет знака. Использование этого означало, что после каждого цикла не было поиска памяти, чтобы получить значение сравнения и не сравнивать. В наши дни большинство компиляторов оптимизируют использование регистра, поэтому память больше не важна, но вы все равно получаете необязательное сравнение.
кстати ставлю 7 или 6 в вашем цикле вводится"магическое число". Для лучшей читаемости вы должны использовать константу с намерением раскрывая имя. Вот так:
const int NUMBER_OF_CARS = 7; for (int i = 0; i < NUMBER_OF_CARS; i++)
EDIT: люди не получают сборку, поэтому, очевидно, требуется более полный пример:
если мы делаем для (i = 0; i
mov esi, 0 loopStartLabel: ; Do some stuff inc esi ; Note cmp command on next line cmp esi, 10 jle exitLoopLabel jmp loopStartLabel exitLoopLabel:
если мы делаем для (int i = 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 C++ не выполняет эту оптимизацию, но делает это, если вы делаете:
for (int i = 10; i >= 0; i--)
таким образом, мораль заключается в том, что если вы используете Microsoft C++†, а восходящий или нисходящий не имеет значения, чтобы получить быстрый цикл, вы должны использовать:
for (int i = 10; i >= 0; i--)
а не любой из этих:
for (int i = 10; i > -1; i--) for (int i = 0; i <= 10; i++)
но, честно говоря, получение читаемости "for (int i = 0; i
† другие компиляторы может делать разные вещи.
С точки зрения оптимизации это не имеет значения.
видно с точки зрения стиля кода я предпочитаю
for ( int i = 0; i < array.size(); i++ )
гораздо более читабельно, чем
for ( int i = 0; i <= array.size() -1; i++ )
также
еще один голос за
@Chris, ваше заявление О.Длина, являющаяся дорогостоящей в .NET, на самом деле не соответствует действительности, а в случае простых типов-наоборот.
int len = somearray.Length; for(i = 0; i < len; i++) { somearray[i].something(); }
на самом деле медленнее, чем
for(i = 0; i < somearray.Length; i++) { somearray[i].something(); }
последний случай, который оптимизирован во время выполнения. Поскольку среда выполнения может гарантировать, что i является допустимым индексом в массиве, проверки границ не выполняются. В первом случае среда выполнения не может гарантировать, что я не был изменен до цикла и принудительно проверяет границы массива для каждого поиск по индексу.
Я предпочитаю:
for (int i = 0; i < 7; i++)
Я думаю, что это более легко переводится на "повторение цикла 7 раз".
Я не уверен в последствиях для производительности - я подозреваю, что любые различия будут скомпилированы.
Это не имеет никакого эффективного значения, когда дело доходит до производительности. Поэтому я бы использовал то, что легче понять в контексте проблемы, которую вы решаете.
в Java 1.5, вы можете просто сделать
for (int i: myArray) { ... }
Так что для массива случае вам не нужно беспокоиться.
Я не думаю, что есть разница в производительности. Вторая форма определенно более читабельна, хотя вам не нужно мысленно вычитать один, чтобы найти номер последней итерации.
EDIT: Я вижу, что другие не согласны. Лично мне нравится видеть фактические номера индексов в структуре цикла. Может быть, это потому, что он больше напоминает Perl
0..6
синтаксис, который я знаю, эквивалентен(0,1,2,3,4,5,6)
. Если я вижу 7, я должен проверить оператора рядом с ним, чтобы смотрите, что на самом деле индекс 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".
В C++, я предпочитаю использовать
!=
, который можно использовать со всеми контейнерами STL. Не все итераторы контейнеров STL менее сопоставимы.
Edsger Dijkstra написал статью об этом еще в 1982 году, где он утверждает, что Нижний
существует наименьшее натуральное число. Исключение нижней границы - как в b) и d) - силы для подпоследовательности, начинающейся с наименьшего натурального числа нижняя граница, как упоминалось в области неестественных чисел. Это уродливо, поэтому для нижней границы мы предпочитаем≤, как в a) и c). Рассмотрим теперь подпоследовательности, начинающиеся с наименьшего натурального число: включение верхней границы заставило бы последнюю быть неестественной к тому времени, когда последовательность сократилась до пустой. Это некрасиво, поэтому для верхней границы мы предпочитаем
во-первых, не используйте 6 или 7.
лучше использовать:
int numberOfDays = 7; for (int day = 0; day < numberOfDays ; day++){ }
в этом случае это лучше, чем с помощью
for (int day = 0; day <= numberOfDays - 1; day++){ }
еще лучше (Java / C#):
for(int day = 0; day < dayArray.Length; i++){ }
и даже лучше (C#)
foreach (int day in days){// day : days in Java }
обратный цикл действительно быстрее, но поскольку его труднее читать (если не Вы другими программистами), лучше избегать. Особенно в разделе C#, Java...
Я согласен с толпой, говоря, что 7 имеет смысл в этом случае, но я бы добавил, что в случае, когда 6 важно, скажем, вы хотите, чтобы ясно, что вы действуете только на объекты до 6-го индекса, то
еще в колледже я помню что-то об этих двух операциях, похожих по вычислительному времени на процессоре. Конечно, мы говорим на уровне сборки.
однако, если вы говорите на C# или Java, я действительно не думаю, что один из них будет ускорением скорости над другим, несколько наносекунд, которые вы получаете, скорее всего, не стоит путаницы, которую вы вводите.
лично я бы написал код, который имеет смысл с точки зрения реализации бизнеса, и убедитесь, что это легко читать.
Это относится непосредственно к категории "Делая Неправильный Код Выглядеть Неправильно".
в языках индексирования на основе нуля, таких как Java или C#, люди привыкли к вариациям на
index < count
состояние. Таким образом, использование этого соглашения defacto сделало бы ошибки off-by-one более очевидными.что касается производительности: любой хороший компилятор стоит его объем памяти должен отображать такие как не проблема.
как небольшое отступление, при циклическом переборе массива или другой коллекции в .Net, я нахожу
foreach (string item in myarray) { System.Console.WriteLine(item); }
чтобы быть более читаемым, чем числовой цикл for. Это, конечно, предполагает, что фактический счетчик Int сам по себе не используется в коде цикла. Я не знаю, есть ли изменение производительности.
привычка использовать
Это почти наверняка имеет большее значение, чем разница в производительности между
еще одно замечание, что было бы лучше быть в привычке делать ++i, а не I++, поскольку fetch и increment требуют временного и increment и fetch не делают. Для целых чисел ваш компилятор, вероятно, оптимизирует временное удаление, но если ваш итерационный тип более сложный, он может быть не в состоянии.
Не используйте магические числа.
почему 7? (или 6, если уж на то пошло).
используйте правильный символ для числа, которое вы хотите использовать...
в этом случае я думаю, что лучше использовать
for ( int i = 0; i < array.size(); i++ )
операторы '
оператор '
использование ++i вместо i++ повышает производительность в C++, но не в C# - я не знаю о Java.
как люди заметили, нет никакой разницы ни в одном из двух вариантов, которые вы упомянули. Просто чтобы подтвердить это, я сделал несколько простых бенчмаркингов в JavaScript.
вы можете увидеть результаты здесь. Что не ясно из этого, так это то, что если я поменяю позицию 1-го и 2-го тестов, результаты для этих двух тестов меняются местами, это явно проблема с памятью. Однако 3-й тест, в котором я меняю порядок итерации, явно быстрее.
как все говорят, принято использовать 0-индексированные итераторы даже для вещей вне массивов. Если все начинается с
0
и заканчивается наn-1
, а нижние границы всегда<=
и верхние границы всегда<
, там гораздо меньше думать, что вы должны сделать при просмотре кода.
большой вопрос. Мой ответ: используйте тип A ('
- вы ясно видите, сколько итераций у вас есть (7).
- разница между двумя конечными точками-это ширина диапазона
- меньше символов делает его более читаемым
- у вас чаще всего есть общее количество элементов
i < strlen(s)
, а не индекс последнего элемента так что единообразие важно.другая проблема связана со всей этой конструкцией.
i
появляется 3 раза в нем, так что это может быть опечатка. Конструкция for-loop говорит как сделать вместо что делать. Я предлагаю принять это:
BOOST_FOREACH(i, IntegerInterval(0,7))
Это более ясно, компилирует в exaclty те же инструкции asm и т. д. Спросите у меня код IntegerInterval, если хотите.
так много ответов ... но я думаю, что мне есть что добавить.
Я предпочитаю, чтобы буквенные числа четко показывали какие значения " я " будет принимать в цикле. Так что в случае итерации, хотя нулевой массив:
for (int i = 0; i <= array.Length - 1; ++i)
и если вы просто зацикливаетесь, а не повторяете массив, подсчет от 1 до 7 довольно интуитивно понятен:
for (int i = 1; i <= 7; ++i)
читаемость превосходит производительность, пока вы не профилируете ее, как вы, вероятно, не знаете, что компилятор или среда выполнения будет делать с вашим кодом до тех пор.
вы также можете использовать . Таким образом, вы получите бесконечный цикл, если вы сделаете ошибку в инициализации, что приведет к тому, что ошибка будет замечена раньше, и любые проблемы, которые она вызывает, будут ограничены застрять в цикле (вместо того, чтобы иметь проблему намного позже и не находить ее).