Какой цикл быстрее, пока или для? - PullRequest
31 голосов
/ 02 сентября 2010

Вы можете получить тот же вывод с циклами for и while:

В то время как:

$i = 0;
while ($i <= 10){
  print $i."\n";
  $i++;
};

Для:

for ($i = 0; $i <= 10; $i++){
  print $i."\n";
}

Но какой из них быстрее?

Ответы [ 16 ]

22 голосов
/ 02 сентября 2010

Это явно зависит от конкретной реализации интерпретатора / компилятора конкретного языка.

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

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

12 голосов
/ 02 сентября 2010

В C # цикл For немного быстрее.

Для среднего значения цикла от 2,95 до 3,02 мс.

Время цикла в среднем составляло от 3,05 до 3,37 мс.

Быстрое маленькое консольное приложение, чтобы доказать:

 class Program
    {
        static void Main(string[] args)
        {
            int max = 1000000000;
            Stopwatch stopWatch = new Stopwatch();

            if (args.Length == 1 && args[0].ToString() == "While")
            {
                Console.WriteLine("While Loop: ");
                stopWatch.Start();
                WhileLoop(max);
                stopWatch.Stop();
                DisplayElapsedTime(stopWatch.Elapsed);
            }
            else
            {
                Console.WriteLine("For Loop: ");
                stopWatch.Start();
                ForLoop(max);
                stopWatch.Stop();
                DisplayElapsedTime(stopWatch.Elapsed);
            }
        }

        private static void WhileLoop(int max)
        {
            int i = 0;
            while (i <= max)
            {
                //Console.WriteLine(i);
                i++;
            };
        }

        private static void ForLoop(int max)
        {
            for (int i = 0; i <= max; i++)
            {
                //Console.WriteLine(i);
            }
        }

        private static void DisplayElapsedTime(TimeSpan ts)
        {
            // Format and display the TimeSpan value.
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds / 10);
            Console.WriteLine(elapsedTime, "RunTime");
        }
    }
6 голосов
/ 02 сентября 2010

Я считаю, что самый быстрый цикл - обратный цикл, например:

var i = myArray.length;
while(i--){
  // Do something
}
5 голосов
/ 02 сентября 2010

Как уже говорили другие, любой компилятор, достойный своей соли, будет генерировать практически идентичный код.Любая разница в производительности ничтожна - вы оптимизируете микро.И это цикл for (по крайней мере, ИМХО).

3 голосов
/ 02 сентября 2010

Установите итерации цикла равными 10000.

Найти время в миллисекундах> Run Loop> найти время в миллисекундах и вычесть первый таймер.

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

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

3 голосов
/ 02 сентября 2010

Если бы это была программа на C, я бы не сказал ни того, ни другого.Компилятор выведет точно такой же код.Поскольку это не так, я говорю, измерить это.На самом деле, дело не в том, какая конструкция цикла быстрее, так как это минимальная экономия времени.Речь идет о том, какую конструкцию цикла легче поддерживать.В случае, который вы показали, цикл for более уместен, потому что это то, что другие программисты (в том числе и вы в будущем, вероятно) ожидают увидеть там.

1 голос
/ 19 июля 2015

Я использовал цикл for и while на тестовом компьютере (нестандартные сторонние фоновые процессы не выполнялись). Я запустил for loop против while loop, поскольку это связано с изменением свойства стиля для 10 000 <button> узлов.

Тест выполнялся последовательно 10 раз, с 1 тайм-аутом на 1500 миллисекунд до выполнения:

Вот очень простой javascript, который я сделал для этой цели

function runPerfTest() {
    "use strict";

    function perfTest(fn, ns) {
        console.time(ns);
        fn();
        console.timeEnd(ns);
    }

    var target = document.getElementsByTagName('button');

    function whileDisplayNone() {
        var x = 0;
        while (target.length > x) {
            target[x].style.display = 'none';
            x++;
        }
    }

    function forLoopDisplayNone() {
        for (var i = 0; i < target.length; i++) {
            target[i].style.display = 'none';
        }
    }

    function reset() {
        for (var i = 0; i < target.length; i++) {
            target[i].style.display = 'inline-block';
        }
    }

    perfTest(function() {
        whileDisplayNone();
    }, 'whileDisplayNone');

    reset();

    perfTest(function() {
        forLoopDisplayNone();
    }, 'forLoopDisplayNone');

    reset();
};

$(function(){
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    setTimeout(function(){
        console.log('cool run');
        runPerfTest();
    }, 1500);
});

Вот результаты, которые я получил

pen.js:8 whileDisplayNone: 36.987ms
pen.js:8 forLoopDisplayNone: 20.825ms

pen.js:8 whileDisplayNone: 19.072ms
pen.js:8 forLoopDisplayNone: 25.701ms

pen.js:8 whileDisplayNone: 21.534ms
pen.js:8 forLoopDisplayNone: 22.570ms

pen.js:8 whileDisplayNone: 16.339ms
pen.js:8 forLoopDisplayNone: 21.083ms

pen.js:8 whileDisplayNone: 16.971ms
pen.js:8 forLoopDisplayNone: 16.394ms

pen.js:8 whileDisplayNone: 15.734ms
pen.js:8 forLoopDisplayNone: 21.363ms

pen.js:8 whileDisplayNone: 18.682ms
pen.js:8 forLoopDisplayNone: 18.206ms

pen.js:8 whileDisplayNone: 19.371ms
pen.js:8 forLoopDisplayNone: 17.401ms

pen.js:8 whileDisplayNone: 26.123ms
pen.js:8 forLoopDisplayNone: 19.004ms

pen.js:61 cool run
pen.js:8 whileDisplayNone: 20.315ms
pen.js:8 forLoopDisplayNone: 17.462ms

Вот демонстрационная ссылка

Обновление

Ниже приведен отдельный тест, в котором реализованы 2 по-разному написанных факториальных алгоритма, один из которых использует цикл for, а другой - цикл while.

Вот код:

function runPerfTest() {
    "use strict";

    function perfTest(fn, ns) {
        console.time(ns);
        fn();
        console.timeEnd(ns);
    }

    function whileFactorial(num) {
        if (num < 0) {
            return -1;
        }
        else if (num === 0) {
            return 1;
        }
        var factl = num;
        while (num-- > 2) {
            factl *= num;
        }
        return factl;
    }

    function forFactorial(num) {
        var factl = 1;
        for (var cur = 1; cur <= num; cur++) {
            factl *= cur;
        }
        return factl;
    }

    perfTest(function(){
        console.log('Result (100000):'+forFactorial(80));
    }, 'forFactorial100');

    perfTest(function(){
        console.log('Result (100000):'+whileFactorial(80));
    }, 'whileFactorial100');
};

(function(){
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    runPerfTest();
    console.log('cold run @1500ms timeout:');
    setTimeout(runPerfTest, 1500);
})();

И результаты факториального теста:

pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.280ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.241ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.254ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.254ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.285ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.294ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.181ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.172ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.195ms
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.279ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.185ms
pen.js:55 cold run @1500ms timeout:
pen.js:38 Result (100000):7.156945704626378e+118
pen.js:8 forFactorial100: 0.404ms
pen.js:41 Result (100000):7.15694570462638e+118
pen.js:8 whileFactorial100: 0.314ms

Вывод: неважно, какой размер выборки или какой тип задачи был протестирован, не существует явного победителя с точки зрения производительности между циклом while и for. Тестирование проводилось на MacAir с OS X Mavericks на вечнозеленом Chrome.

1 голос
/ 02 сентября 2010

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

1 голос
/ 02 сентября 2010

Они должны быть равны. Цикл for, который вы написали, делает то же самое, что и цикл while: устанавливает $i=0, печатает $i и увеличивает $i в конце цикла.

0 голосов
/ 22 мая 2018

Я также пытался сравнить различные типы циклов в C #.Я использовал тот же код, что и у Шейна , но я также попытался с некоторой задержкой и нашел, что он самый быстрый.Это код:

using System;
using System.Diagnostics;


public class Program
{
    public static void Main()
    {
        int max = 9999999;
        Stopwatch stopWatch = new Stopwatch();

        Console.WriteLine("Do While Loop: ");
        stopWatch.Start();
        DoWhileLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
        Console.WriteLine("");
        Console.WriteLine("");

        Console.WriteLine("While Loop: ");
        stopWatch.Start();
        WhileLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
        Console.WriteLine("");
        Console.WriteLine("");

        Console.WriteLine("For Loop: ");
        stopWatch.Start();
        ForLoop(max);
        stopWatch.Stop();
        DisplayElapsedTime(stopWatch.Elapsed);
    }

    private static void DoWhileLoop(int max)
    {
        int i = 0;
        do
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
            i++;
        } while (i <= max);
    }

    private static void WhileLoop(int max)
    {
        int i = 0;
        while (i <= max)
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
            i++;
        };
    }

    private static void ForLoop(int max)
    {
        for (int i = 0; i <= max; i++)
        {
            //Performe Some Operation. By removing Speed increases
            var j = 10 + 10;
            j += 25;
        }
    }

    private static void DisplayElapsedTime(TimeSpan ts)
    {
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

, и это результаты живого демо на DotNetFiddle :

Do While Loop:
0000: 00.06

Во время цикла:
00: 00: 00.13

Для цикла:
00: 00: 00.27

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