Vous pouvez obtenir le même résultat avec les boucles for et while:
Tandis que:
$i = 0;
while ($i <= 10){
print $i."\n";
$i++;
};
Pour:
for ($i = 0; $i <= 10; $i++){
print $i."\n";
}
Mais lequel est le plus rapide?
Cela dépend clairement de l'implémentation particulière de l'interprète/compilateur du langage spécifique.
Cela dit, théoriquement, toute implémentation sensée est susceptible de pouvoir implémenter l’une par rapport à l’autre si elle est plus rapide, la différence doit donc être négligeable.
Bien sûr, j'ai supposé que while
et for
se comportaient comme ils le font dans les langages C et similaires. Vous pouvez créer une langue avec une sémantique complètement différente pour while
et for
En C #, la boucle For est légèrement plus rapide.
Pour la boucle, en moyenne environ 2,95 à 3,02 ms.
La boucle While était en moyenne d’environ 3,05 à 3,37 ms.
Petite application rapide pour prouver:
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");
}
}
Je trouve que la boucle la plus rapide est une boucle while while, par exemple:
var i = myArray.length;
while(i--){
// Do something
}
Comme d'autres l'ont dit, tout compilateur digne de ce nom générera un code pratiquement identique. Toute différence de performance est négligeable - vous effectuez une micro-optimisation.
La vraie question est: qu'est-ce qui est le plus lisible? Et c'est la boucle for
(au moins à mon humble avis).
Si c'était un programme C, je ne dirais ni l'un ni l'autre. Le compilateur produira exactement le même code. Comme ce n'est pas le cas, je dis le mesurer. En réalité, il ne s'agit pas de savoir quelle construction de boucle est la plus rapide, car cela représente un gain de temps minime. Il s'agit de savoir quelle construction de boucle est la plus facile à maintenir. Dans le cas que vous avez montré, une boucle for est plus appropriée car c'est ce que les autres programmeurs (y compris l'avenir, espérons-le) s'attendent à voir là.
Définissez les itérations de la boucle sur 10 000.
Trouvez le temps en millisecondes> Exécuter la boucle> trouvez le temps en millisecondes et soustrayez le premier chronomètre.
Faites-le pour les deux codes, quelle que soit la milliseconde la plus basse exécutée plus rapidement. Vous souhaiterez peut-être exécuter le test plusieurs fois et les répartir afin de réduire la probabilité que des processus en arrière-plan influencent le test.
Vous aurez probablement des temps similaires dans les deux cas, mais je voudrais savoir si on est toujours un peu plus rapide.
J'ai utilisé une boucle for et while sur une machine de test solide (aucun processus d'arrière-plan tiers non standard en cours d'exécution). J'ai exécuté un for loop
vs while loop
en ce qui concerne la modification de la propriété de style de 10 000 nœuds <button>
.
Le test a été exécuté 10 fois consécutives, avec 1 exécution expirée pendant 1 500 millisecondes avant l'exécution:
Voici le javascript très simple que j'ai créé à cet effet
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);
});
Voici les résultats que j'ai obtenus
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
Voici le lien démo
Mettre à jour
Un test séparé que j'ai effectué se trouve ci-dessous et implémente 2 algorithmes factoriels écrits différemment, l'un utilisant une boucle for, l'autre utilisant une boucle while.
Voici le code:
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);
})();
Et les résultats pour le repère factoriel:
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
Conclusion: peu importe la taille de l'échantillon ou le type de tâche spécifique testé, les performances ne sont pas clairement gagnantes entre une boucle while et for. Tests effectués sur un MacAir avec OS X Mavericks sur Chrome evergreen.
Certains compilateurs optimiseurs seront capables de mieux dérouler la boucle avec une boucle for, mais il est probable que si vous faites quelque chose qui peut être déroulé, un compilateur suffisamment intelligent pour le dérouler est probablement assez intelligent pour interpréter la condition de boucle de votre La boucle While peut aussi se dérouler.
Ils devraient être égaux. La boucle for que vous avez écrite fait exactement la même chose que la boucle while: définir $i=0
, imprimer $i
et incrémenter $i
à la fin de la boucle.
J'ai également essayé de comparer les différents types de boucles en C #. J'ai utilisé le même code que Shane , mais j'ai aussi essayé avec un do-while et je l'ai trouvé le plus rapide. C'est le code:
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");
}
}
et voici les résultats d'une démo live sur DotNetFiddle :
Faire en boucle:
00: 00: 00.06En boucle:
00: 00: 00.13Pour boucle:
00: 00: 00.27
En ce qui concerne les boucles infinies, la boucle for(;;)
est meilleure que while(1)
puisque while
évalue chaque fois la condition, mais là encore cela dépend du compilateur.
Dépend de la langue et probablement de son compilateur, mais ils devraient être équivalents dans la plupart des langues.
Je me demandais la même chose alors j'ai cherché sur Google et je me suis retrouvé ici ..__ J'ai fait un petit test en python (extrêmement simple) juste pour voir et voici ce que j'ai obtenu:
Pour:
def for_func(n = 0):
for n in range(500):
n = n + 1
python -m timeit "import for_func; for_func.for_func ()"> pour_func.txt
10000 boucles, meilleur de 3: 40.5 usec par boucle
Tandis que:
def while_func(n = 0):
while n < 500:
n = n + 1
python -m timeit "import while_func; while_func.while_func ()"> while_func.txt
10000 boucles, meilleur de 3: 45 usec par boucle
Peu importe lequel est le plus rapide. Si cela est important, comparez-le à l'aide de votre code réel et voyez par vous-même.
Les réponses à cette autre question pourraient également être utiles: Comment écrire du code plus efficace
Cela dépendra de la mise en œuvre linguistique de ladite boucle, du compilateur et de ce qui ne l’est pas.
La plupart des compilateurs compileront exactement le même code exécutable, par exemple dans CIL (.NET).
Source: vcsjones @ http://forums.asp.net/t/1041090.aspx
Quoi qu'il en soit, le corps de la boucle est l'endroit où le temps de traitement sera dépensé et non la façon dont vous l'itérisez.
Est-ce que techniquement, une boucle For n'est pas un Do?
Par exemple.
for (int i = 0; i < length; ++i)
{
//Code Here.
}
serait...
int i = 0;
do
{
//Code Here.
} while (++i < length);
Je pourrais toutefois avoir tord...
Aussi quand il s'agit de pour les boucles. Si vous prévoyez de ne récupérer que des données et de ne jamais les modifier, vous devez utiliser un foreach. Si vous avez besoin des index réels pour une raison quelconque, vous devrez incrémenter et utiliser la boucle for régulière.
for (Data d : data)
{
d.doSomething();
}
devrait être plus rapide que ...
for (int i = 0; i < data.length; ++i)
{
data[i].doSomething();
}