Forループとwhileループで同じ出力を取得できます。
一方:
$i = 0;
while ($i <= 10){
print $i."\n";
$i++;
};
For:
for ($i = 0; $i <= 10; $i++){
print $i."\n";
}
しかし、どちらが速いですか?
それは明らかに、特定の言語のインタープリター/コンパイラーの特定の実装に依存します。
とはいえ、理論的には、正気の実装であれば、高速であれば、一方を他方の観点から実装できる可能性が高いので、差はせいぜい無視できるはずです。
もちろん、while
とfor
はCや同様の言語でのように振る舞うと仮定しました。 while
とfor
に対してまったく異なるセマンティクスを持つ言語を作成できます
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");
}
}
最速のループは、whileループの逆であることがわかります。
var i = myArray.length;
while(i--){
// Do something
}
他の人が言ったように、その価値があるコンパイラーは実質的に同一のコードを生成します。パフォーマンスの違いはごくわずかです-最適化を行っています。
本当の質問は、もっと読みやすいものは何ですか?そして、それがfor
ループです(少なくともIMHO)。
それがCプログラムである場合、私はどちらとも言えません。コンパイラーはまったく同じコードを出力します。そうではないので、私はそれを測定すると言います。しかし、実際には、どのループ構造が高速であるかということではありません。それは、時間の節約がごくわずかだからです。それは、どのループ構造が保守しやすいかについてです。あなたが示した場合、forループは他のプログラマー(将来のあなたを含む)がそこに期待するものであるため、より適切です。
ループの反復を10,000に設定します。
時間をミリ秒で検索>ループを実行>時間をミリ秒で検索し、最初のタイマーを減算します。
両方のコードに対して実行してください。実行時間が最も短いミリ秒のコードを使用してください。バックグラウンドプロセスがテストに影響を与える可能性を減らすために、テストを複数回実行して平均化することをお勧めします。
どちらも本当に似たような時間になる可能性がありますが、どちらかが常にわずかに速いかどうかを確認したいと思います。
堅牢なテストマシンで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でテストを実施
一部の最適化コンパイラーは、forループでより良いループの展開を行うことができますが、展開できるものを実行している場合、展開するのに十分スマートなコンパイラーは、おそらく、 whileループも展開できます。
それらは等しくなければなりません。作成したforループは、whileループとまったく同じことを実行しています。$i=0
を設定し、$i
を出力し、ループの最後で$i
をインクリメントします。
また、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.06Whileループ:
00:00:00.13Forループ:
00:00:00.27
無限ループに関しては、while
は条件ごとに評価されるため、for(;;)
ループはwhile(1)
よりも優れていますが、これもコンパイラに依存します。
言語とおそらくそのコンパイラに依存しますが、ほとんどの言語で同等でなければなりません。
私は同じことを疑問に思っていたので、グーグルで検索してここに行きました。私は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
どちらが速いかは問題ではありません。重要な場合は、実際のコードを使用してベンチマークを行い、自分で確認してください。
この他の質問への回答も役立つかもしれません: より効率的なコードを書く方法
それは、前述のループの言語実装、コンパイラー、およびそうでないものに依存します。
ほとんどのコンパイラーは、たとえばCIL(.NET)で確実に実行するまったく同じ実行可能コードにコンパイルします。
ソース:vcsjones @ http://forums.asp.net/t/1041090.aspx
いずれにしても、ループの本体は、反復する方法ではなく、処理時間が費やされる場所です。
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();
}