web-dev-qa-db-ja.com

whileまたはforのループはどれですか?

Forループとwhileループで同じ出力を取得できます。

一方:

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

For:

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

しかし、どちらが速いですか?

32
Mark Lalor

それは明らかに、特定の言語のインタープリター/コンパイラーの特定の実装に依存します。

とはいえ、理論的には、正気の実装であれば、高速であれば、一方を他方の観点から実装できる可能性が高いので、差はせいぜい無視できるはずです。

もちろん、whileforはCや同様の言語でのように振る舞うと仮定しました。 whileforに対してまったく異なるセマンティクスを持つ言語を作成できます

22
Mehrdad Afshari

C#では、Forループはわずかに高速です。

ループの平均は約2.95〜3.02ミリ秒です。

Whileループは平均で約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");
        }
    }
12
Shane

最速のループは、whileループの逆であることがわかります。

var i = myArray.length;
while(i--){
  // Do something
}
6
Anthony

他の人が言ったように、その価値があるコンパイラーは実質的に同一のコードを生成します。パフォーマンスの違いはごくわずかです-最適化を行っています。

本当の質問は、もっと読みやすいものは何ですか?そして、それがforループです(少なくともIMHO)。

5
Aillyn

それがCプログラムである場合、私はどちらとも言えません。コンパイラーはまったく同じコードを出力します。そうではないので、私はそれを測定すると言います。しかし、実際には、どのループ構造が高速であるかということではありません。それは、時間の節約がごくわずかだからです。それは、どのループ構造が保守しやすいかについてです。あなたが示した場合、forループは他のプログラマー(将来のあなたを含む)がそこに期待するものであるため、より適切です。

3
nmichaels

ループの反復を10,000に設定します。

時間をミリ秒で検索>ループを実行>時間をミリ秒で検索し、最初のタイマーを減算します。

両方のコードに対して実行してください。実行時間が最も短いミリ秒のコードを使用してください。バックグラウンドプロセスがテストに影響を与える可能性を減らすために、テストを複数回実行して平均化することをお勧めします。

どちらも本当に似たような時間になる可能性がありますが、どちらかが常にわずかに速いかどうかを確認したいと思います。

3
AttackingHobo

堅牢なテストマシンでforおよびwhileループを使用しました(非標準のサードパーティバックグラウンドプロセスは実行されていません)。私はfor loop vs 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

デモリンク

更新

私が実施した別のテストは以下にあります。これは、forループを使用する1つとwhileループを使用する2つの異なる記述の階乗アルゴリズムを実装します。

コードは次のとおりです。

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

結論:テストされたサンプルサイズまたは特定のタスクタイプに関係なく、しばらくの間とforループの間のパフォーマンスの点で明確な勝者はありません。 Chrome evergreen。のOS X MavericksでMacAirでテストを実施

1
Alpha G33k

一部の最適化コンパイラーは、forループでより良いループの展開を行うことができますが、展開できるものを実行している場合、展開するのに十分スマートなコンパイラーは、おそらく、 whileループも展開できます。

1
Chris

それらは等しくなければなりません。作成したforループは、whileループとまったく同じことを実行しています。$i=0を設定し、$iを出力し、ループの最後で$iをインクリメントします。

1
murgatroid99

また、C#でさまざまな種類のループのベンチマークを試みました。 Shaneと同じコード を使用しましたが、do-whileを試してみたところ、最速であることがわかりました。これはコードです:

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ループ:
00:00:00.06

Whileループ:
00:00:00.13

Forループ:
00:00:00.27

0
Mohit Dhawan

無限ループに関しては、whileは条件ごとに評価されるため、for(;;)ループはwhile(1)よりも優れていますが、これもコンパイラに依存します。

0
Ilian Zapryanov

言語とおそらくそのコンパイラに依存しますが、ほとんどの言語で同等でなければなりません。

0
Randolpho

私は同じことを疑問に思っていたので、グーグルで検索してここに行きました。私はpython(非常に単純))で小さなテストを行って、これを確認しました。

For:

def for_func(n = 0):
    for n in range(500):
        n = n + 1

python -m timeit "for_funcをインポート; for_func.for_func()"> for_func.txt

10000ループ、ベスト3:ループあたり40.5 usec

一方:

def while_func(n = 0):
    while n < 500:
        n = n + 1

python -m timeit "while_funcをインポート; while_func.while_func()"> while_func.txt

10000ループ、最高3:ループあたり45 usec

0
niclaslindgren

どちらが速いかは問題ではありません。重要な場合は、実際のコードを使用してベンチマークを行い、自分で確認してください。

この他の質問への回答も役立つかもしれません: より効率的なコードを書く方法

0
David

それは、前述のループの言語実装、コンパイラー、およびそうでないものに依存します。

ほとんどのコンパイラーは、たとえばCIL(.NET)で確実に実行するまったく同じ実行可能コードにコンパイルします。

ソース:vcsjones @ http://forums.asp.net/t/1041090.aspx

いずれにしても、ループの本体は、反復する方法ではなく、処理時間が費やされる場所です。

0
jfrobishow

Forループは技術的にはDo Whileではありませんか?

例えば。

for (int i = 0; i < length; ++i)
{
   //Code Here.
}

だろう...

int i = 0;
do 
{
  //Code Here.
} while (++i < length);

私は間違っている可能性があります...

また、forループに関しても。データのみを取得し、データを変更しない場合は、foreachを使用する必要があります。何らかの理由で実際のインデックスが必要な場合は、増分する必要があるため、通常のforループを使用する必要があります。

for (Data d : data)
{
       d.doSomething();
}

より速いはずです...

for (int i = 0; i < data.length; ++i)
{
      data[i].doSomething();
}
0
Jeremy Trifilo