Какой цикл быстрее for или while
Перейти к содержимому

Какой цикл быстрее for или while

  • автор:

Циклы while и for

При написании скриптов зачастую встаёт задача сделать однотипное действие много раз.

Например, вывести товары из списка один за другим. Или просто перебрать все числа от 1 до 10 и для каждого выполнить одинаковый код.

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

Циклы for…of и for…in

Небольшое объявление для продвинутых читателей.

В этой статье рассматриваются только базовые циклы: while , do..while и for(..;..;..) .

Если вы пришли к этой статье в поисках других типов циклов, вот указатели:

  • См. for…in для перебора свойств объекта.
  • См. for…of и Перебираемые объекты для перебора массивов и перебираемых объектов.

В противном случае, продолжайте читать.

Цикл «while»

Цикл while имеет следующий синтаксис:

while (condition) < // код // также называемый "телом цикла" >

Код из тела цикла выполняется, пока условие condition истинно.

Например, цикл ниже выводит i , пока i < 3 :

let i = 0; while (i < 3) < // выводит 0, затем 1, затем 2 alert( i ); i++; >

Одно выполнение тела цикла по-научному называется итерация. Цикл в примере выше совершает три итерации.

Если бы строка i++ отсутствовала в примере выше, то цикл бы повторялся (в теории) вечно. На практике, конечно, браузер не позволит такому случиться, он предоставит пользователю возможность остановить «подвисший» скрипт, а JavaScript на стороне сервера придётся «убить» процесс.

Любое выражение или переменная может быть условием цикла, а не только сравнение: условие while вычисляется и преобразуется в логическое значение.

Например, while (i) – более краткий вариант while (i != 0) :

let i = 3; while (i) < // когда i будет равно 0, условие станет ложным, и цикл остановится alert( i ); i--; >

Фигурные скобки не требуются для тела цикла из одной строки

Если тело цикла состоит лишь из одной инструкции, мы можем опустить фигурные скобки :

let i = 3; while (i) alert(i--);

Цикл «do…while»

Проверку условия можно разместить под телом цикла, используя специальный синтаксис do..while :

do < // тело цикла >while (condition);

Цикл сначала выполнит тело, а затем проверит условие condition , и пока его значение равно true , он будет выполняться снова и снова.

let i = 0; do < alert( i ); i++; >while (i < 3);

Такая форма синтаксиса оправдана, если вы хотите, чтобы тело цикла выполнилось хотя бы один раз, даже если условие окажется ложным. На практике чаще используется форма с предусловием: while(…) .

Цикл «for»

Более сложный, но при этом самый распространённый цикл — цикл for .

Выглядит он так:

for (начало; условие; шаг) < // . тело цикла . >

Давайте разберёмся, что означает каждая часть, на примере. Цикл ниже выполняет alert(i) для i от 0 до (но не включая) 3 :

for (let i = 0; i < 3; i++) < // выведет 0, затем 1, затем 2 alert(i); >

Рассмотрим конструкцию for подробней:

часть
начало let i = 0 Выполняется один раз при входе в цикл
условие i < 3 Проверяется перед каждой итерацией цикла.
Если оно вычислится в false , цикл остановится.
тело alert(i) Выполняется снова и снова, пока условие вычисляется в true .
шаг i++ Выполняется после тела цикла на каждой итерации перед проверкой условия.

В целом, алгоритм работы цикла выглядит следующим образом:

Выполнить начало → (Если условие == true → Выполнить тело, Выполнить шаг) → (Если условие == true → Выполнить тело, Выполнить шаг) → (Если условие == true → Выполнить тело, Выполнить шаг) → . 

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

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

Вот в точности то, что происходит в нашем случае:

// for (let i = 0; i < 3; i++) alert(i) // Выполнить начало let i = 0; // Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// Если условие == true → Выполнить тело, Выполнить шаг if (i < 3) < alert(i); i++ >// . конец, потому что теперь i == 3

Встроенное объявление переменной

В примере переменная счётчика i была объявлена прямо в цикле. Это так называемое «встроенное» объявление переменной. Такие переменные существуют только внутри цикла.

for (let i = 0; i < 3; i++) < alert(i); // 0, 1, 2 >alert(i); // ошибка, нет такой переменной

Вместо объявления новой переменной мы можем использовать уже существующую:

let i = 0; for (i = 0; i < 3; i++) < // используем существующую переменную alert(i); // 0, 1, 2 >alert(i); // 3, переменная доступна, т.к. была объявлена снаружи цикла

Пропуск частей «for»

Любая часть for может быть пропущена.

Для примера, мы можем пропустить начало если нам ничего не нужно делать перед стартом цикла.

let i = 0; // мы уже имеем объявленную i с присвоенным значением for (; i < 3; i++) < // нет необходимости в "начале" alert( i ); // 0, 1, 2 >

Можно убрать и шаг :

let i = 0; for (; i

Это сделает цикл аналогичным while (i < 3) .

А можно и вообще убрать всё, получив бесконечный цикл:

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

Прерывание цикла: «break»

Обычно цикл завершается при вычислении условия в false .

Но мы можем выйти из цикла в любой момент с помощью специальной директивы break .

Например, следующий код подсчитывает сумму вводимых чисел до тех пор, пока посетитель их вводит, а затем – выдаёт:

let sum = 0; while (true) < let value = +prompt("Введите число", ''); if (!value) break; // (*) sum += value; >alert( 'Сумма: ' + sum );

Директива break в строке (*) полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert .

Вообще, сочетание «бесконечный цикл + break » – отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале или конце цикла, а посередине или даже в нескольких местах его тела.

Переход к следующей итерации: continue

Директива continue – «облегчённая версия» break . При её выполнении цикл не прерывается, а переходит к следующей итерации (если условие все ещё равно true ).

Её используют, если понятно, что на текущем повторе цикла делать больше нечего.

Например, цикл ниже использует continue , чтобы выводить только нечётные значения:

for (let i = 0; i < 10; i++) < // если true, пропустить оставшуюся часть тела цикла if (i % 2 == 0) continue; alert(i); // 1, затем 3, 5, 7, 9 >

Для чётных значений i , директива continue прекращает выполнение тела цикла и передаёт управление на следующую итерацию for (со следующим числом). Таким образом alert вызывается только для нечётных значений.

Директива continue позволяет избегать вложенности

Цикл, который обрабатывает только нечётные значения, мог бы выглядеть так:

for (let i = 0; i < 10; i++) < if (i % 2) < alert( i ); >>

С технической точки зрения он полностью идентичен. Действительно, вместо continue можно просто завернуть действия в блок if .

Однако мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри if более длинный, то это ухудшает читаемость, в отличие от варианта с continue .

Нельзя использовать break/continue справа от оператора „?“

Обратите внимание, что эти синтаксические конструкции не являются выражениями и не могут быть использованы с тернарным оператором ? . В частности, использование таких директив, как break/continue , вызовет ошибку.

Например, если мы возьмём этот код:

if (i > 5) < alert(i); >else

…и перепишем его, используя вопросительный знак:

(i > 5) ? alert(i) : continue; // continue здесь приведёт к ошибке

…то будет синтаксическая ошибка.

Это ещё один повод не использовать оператор вопросительного знака ? вместо if .

Метки для break/continue

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

Например, в коде ниже мы проходимся циклами по i и j , запрашивая с помощью prompt координаты (i, j) с (0,0) до (2,2) :

for (let i = 0; i < 3; i++) < for (let j = 0; j < 3; j++) < let input = prompt(`Значение на координатах ($,$)`, ''); // Что если мы захотим перейти к Готово (ниже) прямо отсюда? > > alert('Готово!');

Нам нужен способ остановить выполнение, если пользователь отменит ввод.

Обычный break после input лишь прервёт внутренний цикл, но этого недостаточно. Достичь желаемого поведения можно с помощью меток.

Метка имеет вид идентификатора с двоеточием перед циклом:

labelName: for (. )

Вызов break в цикле ниже ищет ближайший внешний цикл с такой меткой и переходит в его конец.

outer: for (let i = 0; i < 3; i++) < for (let j = 0; j < 3; j++) < let input = prompt(`Значение на координатах ($,$)`, ''); // если пустая строка или Отмена, то выйти из обоих циклов if (!input) break outer; // (*) // сделать что-нибудь со значениями. > > alert('Готово!');

В примере выше это означает, что вызовом break outer будет разорван внешний цикл до метки с именем outer .

Таким образом управление перейдёт со строки, помеченной (*) , к alert('Готово!') .

Можно размещать метку на отдельной строке:

outer: for (let i = 0; i

Директива continue также может быть использована с меткой. В этом случае управление перейдёт на следующую итерацию цикла с меткой.

Метки не позволяют «прыгнуть» куда угодно

Метки не дают возможности передавать управление в произвольное место кода.

Например, нет возможности сделать следующее:

break label; // не прыгает к метке ниже label: for (. )

Директива break должна находиться внутри блока кода. Технически, подойдет любой маркированный блок кода, например:

label: < // . break label; // работает // . >

…Хотя в 99.9% случаев break используется внутри циклов, как мы видели в примерах выше.

К слову, continue возможно только внутри цикла.

Итого

Мы рассмотрели 3 вида циклов:

  • while – Проверяет условие перед каждой итерацией.
  • do..while – Проверяет условие после каждой итерации.
  • for (;;) – Проверяет условие перед каждой итерацией, есть возможность задать дополнительные настройки.

Чтобы организовать бесконечный цикл, используют конструкцию while (true) . При этом он, как и любой другой цикл, может быть прерван директивой break .

Если на данной итерации цикла делать больше ничего не надо, но полностью прекращать цикл не следует – используют директиву continue .

Обе этих директивы поддерживают метки, которые ставятся перед циклом. Метки – единственный способ для break/continue выйти за пределы текущего цикла, повлиять на выполнение внешнего.

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

for или while (Какой цикл "лучше"?)

Author24 — интернет-сервис помощи студентам

аналогичны (за исключением работы continue в них), так есть ли какое-то преимущество для ресурсов компьютера (для удобства чтения имхо for лучше) или нет?

94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Какой цикл (For, While или Repeat) лучше использовать для решения задач с последовательностями?
Какой цикл For, While или Repeat лучше использовать для решения задач с последовательностями.

Php, подскажите хотя бы какой цикл лучше использовать
Дана строка. Определить сколько раз входит в нее группа букв abc

FASM ИЛИ PUREBESIC ИЛИ ЕСТЬ ЕЩЕ КАКОЙ ТО ЛУЧШЕ ПОДСКАЖИТЕ ?
PUREBESIC НЕ ПОДДЕРЖИВАЕТ КИРИЛЛИЦУ FASM ПОКА НЕ ЗНАЮ КАКОЙ ЛУЧШЕ

Что лучше, учить команды CMD или BASH или PowerShell или все они важны или лучше язык программирования?
В заголовке имел в виду, что если изучаю распространенный язык программирования, например Python.

Регистрация: 19.03.2009
Сообщений: 320

я читал что цикл for более гибкий чем while
в нем можно опустить все три или какое то одно выражение внутри круглых скобок.

for(;;) {это бесконечный цикл}

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

for(int i = 2; i  10; i++) {выражения}

Регистрация: 08.07.2009
Сообщений: 45

По трате ресурсов одинаковы. А вот цикл с постусловием do - while быстрее т.к. в for и while используется лишняя команда перехода. Хотя экономия будет незначительна.

1183 / 468 / 87
Регистрация: 23.06.2009
Сообщений: 6,390

в книгах пишут что for в некоторой степени удобнее,хотя кому как. сам я while-ом пользуюс,мне так удобнее

ЦитатаСообщение от freeman27015 Посмотреть сообщение

это самое можно и с while

while(true){. }

Добавлено через 3 минуты
Zhilidan, for удобнее тем что в нем в отличии от while можно создавать переменные,которые сразу после этого цикла уничтожаются
компилируйте это

1 2 3 4 5 6 7
int a,b; a=b=0; cin>>a>>b; for(int i=0;ia;i++){ cout<"i="<" b="<" a="; } cout<"i="<" b="<" a=";

Регистрация: 26.02.2010
Сообщений: 28

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

Регистрация: 23.10.2009
Сообщений: 250

очень сложный вопрос
отвечу так: каждая строка в С++ это массив char заканчивающийся '\0' или просто 0
по этому мы можем написать так

1 2 3
char *p=new char[128] while(*p) {..}

этот цикл пройдёт без лишних переменных до конца строки однако мы можем сделать так

for (int i=0;p[i]!=0;i++) {}

значение тоже только не удобно

так же существуют численные массивы которые де заканчиваются детерминированным нулем

1 2 3
int *a=new int [n] for(int i=0;in;i++) {..}
1 2 3 4 5
int *a=new int [n] int i=0; while(in){ i++; }

отсюда то что и можно было получить простым переводом
while - пока не что то
for(; ; )- для i от чего то до чего то
что лучше ответь сам

Эксперт PythonЭксперт JavaЭксперт CЭксперт С++

12265 / 7430 / 1740
Регистрация: 25.07.2009
Сообщений: 13,638

ЦитатаСообщение от breate Посмотреть сообщение

мы можем написать так

1 2 3
char *p=new char[128] while(*p) {..}

этот цикл пройдёт без лишних переменных до конца строки однако мы можем сделать так

for (int i=0;p[i]!=0;i++) {}

значение тоже только не удобно
Ну можно и так:

1 2 3 4
char str[] = "abcd", *p; for ( p = str; *p; ++p ){ . }

Регистрация: 23.10.2009
Сообщений: 250
очень интересное предложение
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Какой фильтр лучше: -1/3 2/3 -1/3 или -1/4 1/2 -1/4?
-1/3 2/3 -1/3 -1/4 1/2 -1/4 Преподаватель написал два ряда коэффициентов и спросил какой фильтр.

Какой vb лучше (русский или английский)?
у меня на диске есть версии русская и английская что лучше английский я знаю неплохо но на.

Какой windows(7 или 8.1) лучше в играх?
Какой windows(7 или 8.1) лучше в играх?Обоснуйте пожалуйста свой выбор.

Какой язык лучше изучать C или C++
Всем здравствуйте! Я новичок в программировании(знаю только Паскаль). Сейчас выбираю, какой язык.

Какой язык лучше изучать C# или C++
Подскажите какой язык лучше C# или C++. Изучал C++ но в сети натолкнулся на то что C++ хуже C#.

Или воспользуйтесь поиском по форуму:

while vs foreach vs for что быстрее в php

Один из самых важных и "узких" моментов, скорость работы массива. По массиву меню в процессе построения функции могут пробегать по многу раз, соответственно крайне важно чтоб этот момент работал на максимуме возможностей. давайте разберёмся всю ли правду пишут нам в интернете, какой массив работает быстрее while vs foreach vs for. Часть тестов не несут осмысленной нагрузки - ради интереса добавлены. Каждый тест перезапускался несколько раз.
Необходимо понимать, что тест имеет перекос в сторону обращения к двумерному массиву.

$a=array( 0=>array(0=>'top') ,1=>array(0=>'top') ,2=>array(0=>'top') ,3=>array(0=>'top') ,4=>array(0=>'top') ,5=>array(0=>'left') ,6=>array(0=>'left') ,7=>array(0=>'left') ,8=>array(0=>'left') ,9=>array(0=>'left') ); в функциях function f1() > 2. foreach($a as $k => $v) < if($v[0]=='right')<>> 3. for($i=0; $i > 4. $c=count($a); for($i=0; $i > 5. $c=count($a)-1; for($i=$c; $i>0; --$i) < if($a[$i][0]=='right')<>> 6. reset($a); while(list($k, $v) = each($a)) < if($v[0]=='right')<>> 7. reset($a); while(list(, $v) = each($a)) < if($v[0]=='right')<>> 8. $i=0; while($i ++$i; > 9. $i=0; $c=count($a); while($i <$c)< if($a[$i][0]=='right')<>++$i; > 10. $i=count($a)-1; while($i>-1) < if($a[$i][0]=='right')<>--$i; > 11. $i=count($a)-1; while($i>=0) < if($a[$i][0]=='right')<>--$i; >

Результаты тестирования скорости массивов в PHP

вызовов / функция время быстрее на
1 1 / foreach($a as $v) 0.000018 +0.000006 с. +33.33 %
2 1 / foreach($a as $k => $v) 0.000012 0.000000 с. 0 %
3 1 / for($i=0; $i

0.000036 +0.000024 с. +66.67 %
4 1 / $c=count($a); for($i=0; $i

0.000014 +0.000002 с. +14.29 %
5 1 / $c=count($a)-1; for($i=$c; $i>0; --$i) 0.000022 +0.000010 с. +45.45 %
6 1 / reset($a); while(list($k, $v) = each($a)) 0.000029 +0.000017 с. +58.62 %
7 1 / reset($a); while(list(, $v) = each($a)) 0.000035 +0.000023 с. +65.71 %
8 1 / $i=0; while($i 0.000028 +0.000016 с. +57.14 %
9 1 / $i=0; $c=count($a); while($i<$c) 0.000021 +0.000009 с. +42.86 %
10 1 / $i=count($a)-1; while($i>-1) 0.000013 +0.000001 с. +7.69 %
11 1 / $i=count($a)-1; while($i>=0) 0.000021 +0.000009 с. +42.86 %
вызовов / функция время быстрее на
1 1 / foreach($a as $v) 0.000014 +0.000005 с. +35.71 %
2 1 / foreach($a as $k => $v) 0.000009 0.000000 с. 0 %
3 1 / for($i=0; $i

0.000035 +0.000026 с. +74.29 %
4 1 / $c=count($a); for($i=0; $i

0.000012 +0.000003 с. +25 %
5 1 / $c=count($a)-1; for($i=$c; $i>0; --$i) 0.000020 +0.000011 с. +55 %
6 1 / reset($a); while(list($k, $v) = each($a)) 0.000023 +0.000014 с. +60.87 %
7 1 / reset($a); while(list(, $v) = each($a)) 0.000036 +0.000027 с. +75 %
8 1 / $i=0; while($i 0.000026 +0.000017 с. +65.38 %
9 1 / $i=0; $c=count($a); while($i<$c) 0.000021 +0.000012 с. +57.14 %
10 1 / $i=count($a)-1; while($i>-1) 0.000012 +0.000003 с. +25 %
11 1 / $i=count($a)-1; while($i>=0) 0.000023 +0.000014 с. +60.87 %

В порядке возрастания

вызовов / функция время быстрее на
2 1 / foreach($a as $k => $v) 0.000012 0.000000 с. 0 %
10 1 / $i=count($a)-1; while($i>-1) 0.000013 +0.000001 с. +7.69 %
4 1 / $c=count($a); for($i=0; $i

0.000014 +0.000002 с. +14.29 %
1 1 / foreach($a as $v) 0.000018 +0.000006 с. +33.33 %
9 1 / $i=0; $c=count($a); while($i<$c) 0.000021 +0.000009 с. +42.86 %
11 1 / $i=count($a)-1; while($i>=0) 0.000021 +0.000009 с. +42.86 %
5 1 / $c=count($a)-1; for($i=$c; $i>0; --$i) 0.000022 +0.000010 с. +45.45 %
8 1 / $i=0; while($i 0.000028 +0.000016 с. +57.14 %
6 1 / reset($a); while(list($k, $v) = each($a)) 0.000029 +0.000017 с. +58.62 %
7 1 / reset($a); while(list(, $v) = each($a)) 0.000035 +0.000023 с. +65.71 %
3 1 / for($i=0; $i

0.000036 +0.000024 с. +66.67 %
вызовов / функция время быстрее на
2 1 / foreach($a as $k => $v) 0.000009 0.000000 с. 0 %
10 1 / $i=count($a)-1; while($i>-1) 0.000012 +0.000003 с. +25 %
4 1 / $c=count($a); for($i=0; $i

0.000012 +0.000003 с. +25 %
1 1 / foreach($a as $v) 0.000014 +0.000005 с. +35.71 %
5 1 / $c=count($a)-1; for($i=$c; $i>0; --$i) 0.000020 +0.000011 с. +55 %
9 1 / $i=0; $c=count($a); while($i<$c) 0.000021 +0.000012 с. +57.14 %
6 1 / reset($a); while(list($k, $v) = each($a)) 0.000023 +0.000014 с. +60.87 %
11 1 / $i=count($a)-1; while($i>=0) 0.000023 +0.000014 с. +60.87 %
8 1 / $i=0; while($i 0.000026 +0.000017 с. +65.38 %
3 1 / for($i=0; $i

0.000035 +0.000026 с. +74.29 %
7 1 / reset($a); while(list(, $v) = each($a)) 0.000036 +0.000027 с. +75 %

Выводы

  • Неожиданно foreach показал хороший результат..
  • Не все циклы в обратном порядке работают быстрей.
  • Count внутри цикла работает медленнее, везде об этом пишут - вычисляется на каждом шагу значение.
  • Любые конструкции где php приходиться самому додумывать, обрабатывать пропуски - медленнее, так и здесь while(list(, $v)
  • Больше или равно работает медленнее нежели меньше, поэтому >-1 писать выгоднее нежели >=0 итп.
  • foreach($a as $k=>$v) быстрее чем foreach($a as $v)

Много где пишут, что foreach медленнее остальных циклов, при этом тесты проводят только через foreach($a as $v). Отдельно в следующий раз протестирую что же быстрей for, while на каком-нить синтетическом тесте без обращения к массиву.

Меню раздела "Тесты производительности php"

Страница сгенерирована за 0.001148 сек.
На один процесс веб-сервера: 871 стр./сек.
Всего Apache может отдать: 222 976 стр./сек.
Выделено PHP памяти: 434.35 KB
(real_usage: 2 MB)

Браузер построил за сек.
Полное время сек.

С момента выгрузки предыдущей страницы
из памяти браузера: сек.

Цикл For или While

Это не критично для системы. Для компилятора - это примерно один и тот же набор команд. Тут скорее вопрос в логике и читаемости кода. Хотелось бы увидеть фрагмент кода. И тогда можно решить какой цикл предпочтителен для данной конкретной ситуации.

15 июл 2015 в 17:34

Во-первых, они одинаковы, а во-вторых, джава - это немного не тот язык, для которого имеет смысл спрашивать о подобных вещах. Или имелся в виду foreach?

15 июл 2015 в 17:42
Кто за закрытие голосовал - почему??
15 июл 2015 в 17:42

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Вы опоздали с вашим вопросом лет эдак на 30-40.

Сейчас никакой разницы нет, вообще. Компиляторы умные, и если смысл кода по сути один и тот же, обычно производят одинаковый байткод.

Кроме того, даже если бы производительность разных видов циклов и отличалась, расходы времени на управление циклами составляют порядка нескольких наносекунд. «Оптимизация» такого толка вам ничего не принесёт: расходы на запуск приложения (чтение его из файловой системы) на несколько порядков больше.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *