Что может быть лучшим способом зацикливания на двух диапазонах - умножить их вместе и сделать это одним циклом или зациклить каждый диапазон отдельно? - PullRequest
1 голос
/ 12 августа 2010

Я не могу решить, как мне перебрать диапазоны.Так:

for (int i = 0; i < max_i; i++) {
    for (int j = 0; j < max_j; j++) {
        // first way - two loops
    }
}

Или вот так:

for (int k = 0; k < max_i*max_j; k++) {
    // second way - one loop
}

Спасибо, Бода Кидо.

Ответы [ 10 ]

7 голосов
/ 12 августа 2010

Это зависит от того, что вы будете делать с индексами.Если вы используете два значения по отдельности (например, вы перебираете все перестановки значений в двух циклах), тогда решение с двумя циклами будет более понятным.Стратегия с одним циклом лучше, если вы заботитесь не об отдельных ценностях, а об их продукте.

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

4 голосов
/ 12 августа 2010

Первый цикл лучше по двум причинам, по крайней мере:

  1. Это может сделать понятным читателю вложенную природу циклов (в зависимости от того, что требуется)
  2. Что произойдет, если max_i * max_j переполнится во второй альтернативе?

Также, пожалуйста, выясните, должны ли переменные индекса цикла быть int или size_t.size_t всегда будет положительным

3 голосов
/ 12 августа 2010

Вы не можете использовать второй вариант, когда max_i или / и max_j достаточно велики.Обратите внимание, что int является типом со знаком.Если sizeof(int) равно 4 байта, то в случае, когда max_i=32768 и max_j=65536 ваш цикл будет выполняться ноль раз.

Если нет особых требований, я бы предпочел первый вариант, так как онболее читабельно.

2 голосов
/ 12 августа 2010

Очевидно, что если у вас есть выбор, вам не нужно точное значение i и j во время цикла.

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

int iKMax = max_i*max_j;
for (int k = 0; k < iKMax ; ++k)  
{
    // second way - one loop
}

И всегда используйте префиксный оператор в циклах (++ k), потому что независимо от того, какой объект повторяется, он экономит одно копирование этого объекта. (См. Херб Саттер и Андрей Александреску, «Стандарты кодирования C ++: 101 правила, руководящие указания и передовой опыт»)

2 голосов
/ 12 августа 2010

Если вы решили пойти по первому пути, то все хорошо, потому что у вас есть значения как i, так и j. Вторым способом вы должны получить значения i и j вручную:

for (int k = 0; k < max_i*max_j; k++) {
    i = k / max_j;
    j = k % max_j;
    ....
}

Итак, первый способ определенно лучше в вашем случае.

2 голосов
/ 12 августа 2010

Зависит от того, что вы делаете внутри цикла. Вам нужны индексы i и j? Тогда я бы предпочел первое решение.

0 голосов
/ 14 августа 2010

Вот еще один способ сделать это:

для (int i = 0, j = 0; i <max_i, j

0 голосов
/ 13 августа 2010

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

Это определенно не так для таких вещей, как Android 1.0, но большинство компиляторов C / C ++ достаточно хороши. Хороший компилятор должен иметь возможность оптимизировать простой доступ к двумерному массиву (например, суммирование всех значений массива) в один цикл.

0 голосов
/ 12 августа 2010

Если вы используете двумерный массив, то первый становится гораздо более читабельным.В прежние времена было как-то распространено эмулировать 2d-массивы с 1D, но и в этом случае первый более читабелен.

0 голосов
/ 12 августа 2010

Ну, это зависит. Если вы хотите отдельные индексы , вы можете использовать первый. если вам нужен только одиночный индекс , тогда второй.

Сложность обоих циклов одинакова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...