Si vous deviez parcourir une boucle 7 fois, utiliseriez-vous:
for (int i = 0; i < 7; i++)
ou:
for (int i = 0; i <= 6; i++)
Il y a deux considérations:
Pour les performances, je suppose que Java ou C #. Est-ce important si "inférieur à" ou "inférieur ou égal à" est utilisé? Si vous avez un aperçu d'un autre langage, veuillez indiquer lequel .
Pour plus de lisibilité, je suppose des tableaux basés sur 0.
PD: Ma mention de tableaux basés sur 0 peut avoir confondu les choses. Je ne parle pas d'itérer à travers des éléments de tableau. Juste une boucle générale.
Il y a un bon point ci-dessous sur l'utilisation d'une constante qui expliquerait ce qu'est ce nombre magique. Donc, si j'avais "int NUMBER_OF_THINGS = 7
" puis "i <= NUMBER_OF_THINGS - 1
"aurait l'air bizarre, non?.
Le premier est plus idiomatique . En particulier, il indique (dans un sens basé sur 0) le nombre d'itérations. Lorsque j'utilise quelque chose basé sur 1 (par exemple JDBC, IIRC), je pourrais être tenté d'utiliser <=. Alors:
for (int i=0; i < count; i++) // For 0-based APIs
for (int i=1; i <= count; i++) // For 1-based APIs
Je m'attendrais à ce que la différence de performances soit insignifiante dans le code du monde réel.
Ces deux boucles itèrent 7 fois. Je dirais que celui avec un 7 est plus lisible/plus clair, sauf si vous avez une très bonne raison pour l'autre.
Je me souviens de mes jours où nous avons fait 8086 Assembly au collège, c'était plus performant de faire:
for (int i = 6; i > -1; i--)
car il y avait une opération JNS qui signifie Jump if No Sign. L'utilisation de cela signifiait qu'il n'y avait pas de recherche de mémoire après chaque cycle pour obtenir la valeur de comparaison et aucune comparaison non plus. De nos jours, la plupart des compilateurs optimisent l'utilisation des registres, de sorte que la mémoire n'est plus importante, mais vous obtenez toujours une comparaison non requise.
Soit dit en passant, mettre 7 ou 6 dans votre boucle introduit un " nombre magique ". Pour une meilleure lisibilité, vous devez utiliser une constante avec un nom révélateur d'intention. Comme ça:
const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)
EDIT: Les gens ne reçoivent pas le truc de l'Assemblée, donc un exemple plus complet est évidemment nécessaire:
Si nous faisons pour (i = 0; i <= 10; i ++), vous devez le faire:
mov esi, 0
loopStartLabel:
; Do some stuff
inc esi
; Note cmp command on next line
cmp esi, 10
jle exitLoopLabel
jmp loopStartLabel
exitLoopLabel:
Si nous le faisons pour (int i = 10; i> -1; i--), alors vous pouvez vous en sortir:
mov esi, 10
loopStartLabel:
; Do some stuff
dec esi
; Note no cmp command on next line
jns exitLoopLabel
jmp loopStartLabel
exitLoopLabel:
Je viens de vérifier et le compilateur C++ de Microsoft ne fait pas cette optimisation, mais il le fait si vous le faites:
for (int i = 10; i >= 0; i--)
Donc, la morale est que si vous utilisez Microsoft C++ †, et que la montée ou la descente ne fait aucune différence, pour obtenir une boucle rapide, vous devez utiliser:
for (int i = 10; i >= 0; i--)
plutôt que l'un ou l'autre:
for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)
Mais franchement, obtenir la lisibilité de "for (int i = 0; i <= 10; i ++)" est normalement beaucoup plus important que de manquer une commande de processeur.
† D'autres compilateurs peuvent faire des choses différentes.
J'utilise toujours <array.length car il est plus facile à lire que <= array.length-1.
ayant également <7 et étant donné que vous savez que cela commence par un index 0, il devrait être intuitif que le nombre soit le nombre d'itérations.
Vu d'un point de vue optimisant, cela n'a pas d'importance.
Vu d'un point de vue de style de code, je préfère <. Raison:
for ( int i = 0; i < array.size(); i++ )
est tellement plus lisible que
for ( int i = 0; i <= array.size() -1; i++ )
<vous donne également le nombre d'itérations immédiatement.
Un autre vote pour <est que vous pourriez éviter beaucoup d'erreurs accidentelles ponctuelles.
@Chris, Votre déclaration sur le fait que .Length coûte cher dans .NET est en fait fausse et dans le cas des types simples, c'est exactement le contraire.
int len = somearray.Length;
for(i = 0; i < len; i++)
{
somearray[i].something();
}
est en fait plus lent que
for(i = 0; i < somearray.Length; i++)
{
somearray[i].something();
}
Le dernier est un cas optimisé par le runtime. Étant donné que le runtime peut garantir que i est un index valide dans le tableau, aucune vérification des limites n'est effectuée. Dans le premier, le runtime ne peut garantir que je n'ai pas été modifié avant la boucle et force les vérifications des limites sur le tableau pour chaque recherche d'index.
Cela ne fait aucune différence en termes de performances. Par conséquent, j'utiliserais ce qui est plus facile à comprendre dans le contexte du problème que vous résolvez.
Je préfère:
for (int i = 0; i < 7; i++)
Je pense que cela se traduit plus facilement par "itérer 7 fois dans une boucle".
Je ne suis pas sûr des implications en termes de performances - je soupçonne que toute différence serait compilée.
Dans Java 1.5 vous pouvez simplement faire
for (int i: myArray) {
...
}
donc pour le cas du tableau, vous n'avez pas à vous inquiéter.
Je ne pense pas qu'il y ait de différence de performance. Le deuxième formulaire est certainement plus lisible, vous n'avez pas à en soustraire mentalement un pour trouver le dernier numéro d'itération.
EDIT: Je vois d'autres en désaccord. Pour moi personnellement, j'aime voir les numéros d'index réels dans la structure de la boucle. C'est peut-être parce que cela rappelle plus la syntaxe 0..6
De Perl, qui je sais est équivalente à (0,1,2,3,4,5,6)
. Si je vois un 7, je dois vérifier l'opérateur à côté de lui pour voir qu'en fait, l'index 7 n'est jamais atteint.
Je dirais utiliser la version "<7" parce que c'est ce que la majorité des gens liront - donc si les gens lisent votre code, ils pourraient l'interpréter à tort.
Je ne m'inquiéterais pas de savoir si "<" est plus rapide que "<=", optez simplement pour la lisibilité.
Si vous voulez opter pour une augmentation de vitesse, tenez compte des points suivants:
for (int i = 0; i < this->GetCount(); i++)
{
// Do something
}
Pour augmenter les performances, vous pouvez légèrement le réorganiser pour:
const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
// Do something
}
Notez la suppression de GetCount () de la boucle (car cela sera interrogé dans chaque boucle) et le changement de "i ++" en "++ i".
Edsger Dijkstra a écrit un article à ce sujet en 1982 où il plaide pour <<i <upper <:
Il existe un plus petit nombre naturel. L'exclusion de la borne inférieure - comme en b) et d) - force pour une sous-séquence commençant au plus petit nombre naturel la borne inférieure comme mentionné dans le domaine des nombres non naturels. C'est moche, donc pour la borne inférieure, nous préférons le ≤ comme dans a) et c). Considérez maintenant les sous-séquences commençant au plus petit nombre naturel: l'inclusion de la borne supérieure forcerait alors ce dernier à ne pas être naturel au moment où la séquence s'est rétrécie pour devenir vide. C'est moche, donc pour la borne supérieure, nous préférons <comme dans a) et d). Nous concluons que la convention a) doit être préférée.
En C++, je préfère utiliser !=
, utilisable avec tous les conteneurs STL. Tous les itérateurs de conteneurs STL ne sont pas comparables.
Tout d'abord, n'utilisez pas 6 ou 7.
Mieux utiliser:
int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){
}
Dans ce cas, c'est mieux que d'utiliser
for (int day = 0; day <= numberOfDays - 1; day++){
}
Encore mieux (Java/C #):
for(int day = 0; day < dayArray.Length; i++){
}
Et encore mieux (C #)
foreach (int day in days){// day : days in Java
}
La boucle inverse est en effet plus rapide mais comme c'est plus difficile à lire (sinon par vous par d'autres programmeurs), il vaut mieux éviter dedans. Surtout en C #, Java ...
Je suis d'accord avec la foule qui dit que le 7 a du sens dans ce cas, mais j'ajouterais que dans le cas où le 6 est important, disons que vous voulez préciser que vous n'agissez que sur des objets jusqu'au 6ème index, puis le <= est meilleur car il rend les 6 plus faciles à voir.
De retour à l'université, je me souviens que ces deux opérations étaient similaires en temps de calcul sur le CPU. Bien sûr, nous parlons au niveau de l'Assemblée.
Cependant, si vous parlez C # ou Java, je ne pense vraiment pas que l'un va augmenter la vitesse par rapport à l'autre.Les quelques nanosecondes que vous gagnez ne valent probablement pas la confusion que vous introduisez.
Personnellement, j'écrirais le code qui a du sens du point de vue de l'implémentation métier et je m'assurerais qu'il est facile à lire.
Cela tombe directement sous la catégorie "Rendre le mauvais code faux" .
Dans les langages d'indexation à base zéro, tels que Java ou C #, les utilisateurs sont habitués aux variations du index < count
condition. Ainsi, tirer parti de cette convention de facto rendrait les erreurs de coup par coup plus évidentes.
Concernant les performances: tout bon compilateur digne de son encombrement mémoire doit être rendu tel qu'un non-problème.
En passant, lorsque je fais une boucle dans un tableau ou une autre collection en .Net, je trouve
foreach (string item in myarray)
{
System.Console.WriteLine(item);
}
pour être plus lisible que la boucle for numérique. Cela suppose bien sûr que le compteur réel Int lui-même n'est pas utilisé dans le code de boucle. Je ne sais pas s'il y a un changement de performance.
Prendre l'habitude d'utiliser <le rendra cohérent pour vous et le lecteur lorsque vous parcourez un tableau. Il sera plus simple pour tout le monde d'avoir une convention standard. Et si vous utilisez un langage avec des tableaux basés sur 0, <est la convention.
Cela importe certainement plus que toute différence de performances entre <et <=. Visez d'abord la fonctionnalité et la lisibilité, puis optimisez.
Une autre remarque est qu'il serait préférable d'avoir l'habitude de faire ++ i plutôt que i ++, car fetch et increment nécessite un temporaire et increment et fetch ne le fait pas. Pour les entiers, votre compilateur optimisera probablement l'écart temporaire, mais si votre type d'itération est plus complexe, il pourrait ne pas être en mesure de le faire.
Vous pouvez également utiliser !=
au lieu. De cette façon, vous obtiendrez une boucle infinie si vous faites une erreur lors de l'initialisation, ce qui fait que l'erreur est remarquée plus tôt et que tout problème qu'elle provoque se limite à rester coincé dans la boucle (plutôt que d'avoir un problème beaucoup plus tard et de ne pas trouver il).
N'utilisez pas de nombres magiques.
Pourquoi est-il 7? (ou 6 d'ailleurs).
utilisez le bon symbole pour le nombre que vous souhaitez utiliser ...
Dans ce cas, je pense qu'il vaut mieux utiliser
for ( int i = 0; i < array.size(); i++ )
Grande question. Ma réponse: utilisez le type A ('<')
i < strlen(s)
plutôt que l'index du dernier élément donc l'uniformité est importante.Un autre problème est avec toute cette construction. i
apparaît fois dedans, donc il peut être mal tapé. La construction for-loop dit comment faire au lieu de que faire. Je suggère d'adopter ceci:
BOOST_FOREACH(i, IntegerInterval(0,7))
C'est plus clair, compile pour exaclty les mêmes instructions asm, etc. Demandez-moi le code d'IntegerInterval si vous le souhaitez.
Tant de réponses ... mais je crois que j'ai quelque chose à ajouter.
Ma préférence est que les nombres littéraux indiquent clairement quelles valeurs "i" prendra dans la boucle. Donc, dans le cas d'une itération à partir d'un tableau à base zéro:
for (int i = 0; i <= array.Length - 1; ++i)
Et si vous êtes en boucle, pas en itération dans un tableau, compter de 1 à 7 est assez intuitif:
for (int i = 1; i <= 7; ++i)
La lisibilité l'emporte sur les performances jusqu'à ce que vous le profiliez, car vous ne savez probablement pas ce que le compilateur ou l'exécution va faire avec votre code jusque-là.
Comme les gens l'ont observé, il n'y a pas de différence dans les deux alternatives que vous avez mentionnées. Juste pour confirmer cela, j'ai fait quelques analyses comparatives simples en JavaScript.
Vous pouvez voir les résultats ici . Ce qui n'est pas clair, c'est que si j'échange la position des 1er et 2e tests, les résultats de ces 2 tests s'échangent, c'est clairement un problème de mémoire. Cependant le 3ème test, celui où j'inverse l'ordre de l'itération est nettement plus rapide.
Il y a plusieurs bonnes raisons d'écrire i <7. Avoir le numéro 7 dans une boucle qui répète 7 fois est bien. La performance est effectivement identique. Presque tout le monde écrit i <7. Si vous écrivez pour plus de lisibilité, utilisez le formulaire que tout le monde reconnaîtra instantanément.
Comme tout le monde le dit, il est habituel d'utiliser des itérateurs indexés 0 même pour des choses en dehors des tableaux. Si tout commence à 0
et se termine à n-1
et les bornes inférieures sont toujours <=
et les limites supérieures sont toujours <
, il y a beaucoup moins de réflexion à faire lors de l'examen du code.
Les opérateurs "<" et "<=" ont exactement le même coût de performance.
L'opérateur "<" est un standard et plus facile à lire dans une boucle de base zéro.
L'utilisation de ++ i au lieu d'i ++ améliore les performances en C++, mais pas en C # - je ne connais pas Java.
J'ai toujours préféré:
for ( int count = 7 ; count > 0 ; -- count )
Aucune différence de vitesse, mais <est plus susceptible d'être correct dans une langue avec des tableaux basés sur 0. De plus, si vous voulez répéter vers le bas au lieu de monter, vous pouvez dire:
for (i = 7; --i >= 0; ) ...
Il ne devrait pas y avoir de différence de performances au moins avec les compilateurs x86. JL et JLE travaille en même temps, dès que je sais. Et en ce qui concerne la redability, l'utilisation de "<7" pour un tableau de sept éléments est logique.
Je dirais que cela devrait être <.
Pourquoi utiliser beaucoup de mots quand quelques-uns suffiront. Un test est plus facile à comprendre que deux. Par conséquent, il est plus facile de tester et de modifier les unités à l'avenir.
La différence est-elle petite? Oui. Mais pourquoi ajouter de la complexité quand cela n'est pas justifié.
Enfin, vous ne dépendez d'aucun optimiseur ou implémentation d'un interpréteur lorsque le code est optimisé pour commencer. Pour citer Einstein, "restez aussi simple que possible mais pas plus simple".
Je suis la première méthode car cet idiome est répété fréquemment.
for (int index = 0; index <array.length; i ++)
String s = oldString.substring (0, numChars);
etc.
Je suis habitué à ce que la limite supérieure soit exclue, et je préférerais que cela reste ainsi sauf s'il y a de bonnes raisons de la changer. (exemple - indexation basée sur 1)
Optez d'abord pour la lisibilité, optimisez plus tard (même si, honnêtement, je ne peux imaginer aucune différence qui serait perceptible).
Sachez que la forme 0 -> K est un idiome C transmis en C # en ayant des tableaux basés sur 0. Suivez l'idiome et ne violez pas le principe du moindre étonnement.
Je préfère ça:
for (int i = 0; i < 7; i++)
Cependant (ce n'est qu'une idée), la lisibilité de celui-ci pourrait avoir à faire si les tableaux sont basés sur 0 (C #, Java) ou 1 (VB .NET). Je dis cela parce que lorsque vous travaillez avec des tableaux basés sur 0, vous obtenez dans un état d'esprit que 0-6 s'exécuterait 7 fois. Je pense que 0-6 est plus intuitif que 1-7. Là encore, je viens d'un milieu C++, Java, C #.
Pour certains langages/technologies comme .NET, utiliser .Size ou .Length ou size ()/length () est une mauvaise idée, car il accède à cette propriété à chaque itération, donc l'affecter à une variable a un impact sur les performances légèrement inférieur.
Je pense que les deux sont OK, mais quand vous avez choisi, respectez l'un ou l'autre. Si vous avez l'habitude d'utiliser <=, essayez de ne pas utiliser <et vice versa.
Je préfère <=, mais dans les situations où vous travaillez avec des index qui commencent à zéro, j'essaierais probablement d'utiliser <. C'est une préférence personnelle cependant.
D'un point de vue logique, il faut penser que < count
serait plus efficace que <= count
pour la raison exacte que <=
testera également l'égalité.
L'optimisation prématurée est la racine de tout Mal. Optez pour la lisibilité à moins qu'il n'y ait une très bonne raison de vous inquiéter pour <
plus de <=
.