Wenn Sie eine Schleife sieben Mal durchlaufen müssten, würden Sie Folgendes verwenden:
for (int i = 0; i < 7; i++)
oder:
for (int i = 0; i <= 6; i++)
Es gibt zwei Überlegungen:
- Performance
- Lesbarkeit
Für die Leistung gehe ich von Java oder C # aus. Ist es wichtig, ob "kleiner als" oder "kleiner als oder gleich" verwendet wird? Wenn Sie Einblick in eine andere Sprache haben, geben Sie bitte an, welche.
Zur besseren Lesbarkeit gehe ich von 0-basierten Arrays aus.
UPD: Meine Erwähnung von 0-basierten Arrays hat die Dinge möglicherweise verwirrt. Ich spreche nicht über das Durchlaufen von Array-Elementen. Nur eine allgemeine Schleife.
Es gibt unten einen guten Punkt über die Verwendung einer Konstante, die erklären würde, was diese magische Zahl ist. Wenn ich also " int NUMBER_OF_THINGS = 7
" dann " i <= NUMBER_OF_THINGS - 1
" hätte, würde es komisch aussehen, nicht wahr?
quelle
Antworten:
Der erste ist idiomatischer . Insbesondere gibt es (in einem 0-basierten Sinne) die Anzahl der Iterationen an. Wenn ich etwas 1-basiertes (z. B. JDBC, IIRC) verwende, könnte ich versucht sein, <= zu verwenden. So:
Ich würde erwarten, dass der Leistungsunterschied im realen Code unbedeutend gering ist.
quelle
Beide Schleifen werden sieben Mal wiederholt. Ich würde sagen, der eine mit einer 7 ist besser lesbar / klarer, es sei denn, Sie haben einen wirklich guten Grund für den anderen.
quelle
Ich erinnere mich an meine Tage, als wir 8086 Assembly am College machten, war es performanter:
da es eine JNS- Operation gab, die Jump if No Sign bedeutet. Dies bedeutete, dass nach jedem Zyklus keine Speichersuche durchgeführt wurde, um den Vergleichswert zu erhalten, und auch kein Vergleich. Heutzutage optimieren die meisten Compiler die Registernutzung, sodass die Speichersache nicht mehr wichtig ist, Sie aber dennoch einen nicht benötigten Vergleich erhalten.
Übrigens führt das Einfügen von 7 oder 6 in Ihre Schleife eine " magische Zahl " ein. Zur besseren Lesbarkeit sollten Sie eine Konstante mit einem absichtlichen Namen verwenden. So was:
EDIT: Die Leute bekommen die Montagesache nicht, daher ist offensichtlich ein vollständigeres Beispiel erforderlich:
Wenn wir für (i = 0; i <= 10; i ++) tun, müssen Sie dies tun:
Wenn wir für (int i = 10; i> -1; i--) tun, können Sie damit durchkommen:
Ich habe es gerade überprüft und der C ++ - Compiler von Microsoft führt diese Optimierung nicht durch, aber wenn Sie Folgendes tun:
Die Moral lautet also: Wenn Sie Microsoft C ++ † verwenden und das Auf- oder Absteigen keinen Unterschied macht, sollten Sie Folgendes verwenden, um eine schnelle Schleife zu erhalten:
eher als eines von diesen:
Offen gesagt ist es jedoch weitaus wichtiger, die Lesbarkeit von "for (int i = 0; i <= 10; i ++)" zu erhalten, als einen Prozessorbefehl zu verpassen.
† Andere Compiler können andere Dinge tun.
quelle
7-i
alle Optimierungen überfluten, die Sie durch das Rückwärtszählen erhalten.Ich verwende immer <array.length, weil es einfacher zu lesen ist als <= array.length-1.
Wenn Sie auch <7 haben und wissen, dass es mit einem 0-Index beginnt, sollte es intuitiv sein, dass die Anzahl die Anzahl der Iterationen ist.
quelle
Unter optimierenden Gesichtspunkten spielt es keine Rolle.
Aus der Sicht des Codestils bevorzuge ich <. Grund:
ist so viel lesbarer als
Außerdem gibt <Ihnen sofort die Anzahl der Iterationen an.
Eine weitere Abstimmung für <ist, dass Sie möglicherweise viele versehentliche Fehler nacheinander verhindern.
quelle
@Chris, Ihre Aussage, dass .Length in .NET teuer ist, ist eigentlich falsch und bei einfachen Typen genau das Gegenteil.
ist eigentlich langsamer als
Letzteres ist ein Fall, der durch die Laufzeit optimiert wird. Da die Laufzeit garantieren kann, dass i ein gültiger Index für das Array ist, werden keine Grenzüberprüfungen durchgeführt. Im ersteren Fall kann die Laufzeit nicht garantieren, dass ich vor der Schleife nicht geändert wurde, und erzwingt bei jeder Indexsuche Grenzprüfungen für das Array.
quelle
.lenght
OR auf.size
. Ich bin mir nicht sicher, aber nicht sicher, aber ich möchte nur sicher gehen.Es macht keinen effektiven Unterschied, wenn es um Leistung geht. Daher würde ich verwenden, was im Kontext des von Ihnen gelösten Problems leichter zu verstehen ist.
quelle
Ich bevorzuge:
Ich denke, das lässt sich leichter in "7-maliges Durchlaufen einer Schleife" übersetzen.
Ich bin mir nicht sicher über die Auswirkungen auf die Leistung - ich vermute, dass Unterschiede weg kompiliert werden.
quelle
In Java 1.5 können Sie dies einfach tun
Für den Array-Fall brauchen Sie sich also keine Sorgen zu machen.
quelle
Ich glaube nicht, dass es einen Leistungsunterschied gibt. Die zweite Form ist definitiv besser lesbar. Sie müssen keine mental subtrahieren, um die letzte Iterationsnummer zu finden.
EDIT: Ich sehe andere nicht einverstanden. Für mich persönlich möchte ich die tatsächlichen Indexnummern in der Schleifenstruktur sehen. Vielleicht liegt es daran, dass es eher an Perls
0..6
Syntax erinnert, von der ich weiß, dass sie gleichbedeutend ist(0,1,2,3,4,5,6)
. Wenn ich eine 7 sehe, muss ich den Operator daneben überprüfen, um festzustellen, dass der Index 7 tatsächlich nie erreicht wird.quelle
Ich würde sagen, verwenden Sie die "<7" -Version, da dies die Mehrheit der Leute liest. Wenn also Leute Ihren Code überfliegen, interpretieren sie ihn möglicherweise falsch.
Ich würde mir keine Sorgen machen, ob "<" schneller als "<=" ist, sondern nur die Lesbarkeit verbessern.
Wenn Sie eine Geschwindigkeitssteigerung anstreben, sollten Sie Folgendes berücksichtigen:
Um die Leistung zu steigern, können Sie sie leicht neu anordnen auf:
Beachten Sie das Entfernen von GetCount () aus der Schleife (da dies in jeder Schleife abgefragt wird) und die Änderung von "i ++" in "++ i".
quelle
In C ++ bevorzuge ich die Verwendung
!=
, die mit allen STL-Containern verwendet werden kann. Nicht alle STL-Container-Iteratoren sind weniger als vergleichbar.quelle
Edsger Dijkstra schrieb 1982 einen Artikel darüber, in dem er sich für das untere <= i <obere aussprach:
quelle
Verwenden Sie zuerst nicht 6 oder 7.
Besser zu verwenden:
In diesem Fall ist es besser als zu verwenden
Noch besser (Java / C #):
Und noch besser (C #)
Die Rückwärtsschleife ist zwar schneller, aber da sie schwerer zu lesen ist (wenn nicht von anderen Programmierern), ist es besser, sie zu vermeiden. Insbesondere in C #, Java ...
quelle
Ich stimme der Menge zu, die sagt, dass die 7 in diesem Fall sinnvoll ist, aber ich möchte hinzufügen, dass Sie in dem Fall, in dem die 6 wichtig ist, klarstellen möchten, dass Sie nur auf Objekte bis zum 6. Index und dann auf den 6. Index einwirken <= ist besser, da es die 6 leichter zu sehen macht.
quelle
Ich erinnere mich, dass diese beiden Operationen in der Rechenzeit auf der CPU ähnlich waren. Natürlich reden wir auf Montageebene.
Wenn Sie jedoch von C # oder Java sprechen, glaube ich wirklich nicht, dass einer die Geschwindigkeit gegenüber dem anderen steigern wird. Die wenigen Nanosekunden, die Sie gewinnen, sind höchstwahrscheinlich keine Verwirrung wert, die Sie einführen.
Persönlich würde ich den Code verfassen, der vom Standpunkt der Geschäftsimplementierung aus sinnvoll ist, und sicherstellen, dass er leicht zu lesen ist.
quelle
Dies fällt direkt unter die Kategorie "Falschen Code falsch aussehen lassen" .
In auf Null basierenden Indexierungssprachen wie Java oder C # sind Benutzer an Variationen der
index < count
Bedingung gewöhnt . Die Nutzung dieser Defacto-Konvention würde also Fehler nacheinander offensichtlicher machen.In Bezug auf die Leistung: Jeder gute Compiler, der seinen Speicherbedarf wert ist, sollte beispielsweise kein Problem darstellen.
quelle
Nebenbei bemerkt, wenn ich ein Array oder eine andere Sammlung in .Net durchlaufe, finde ich
besser lesbar sein als die numerische for-Schleife. Dies setzt natürlich voraus, dass der tatsächliche Zähler Int selbst nicht im Schleifencode verwendet wird. Ich weiß nicht, ob es eine Leistungsänderung gibt.
quelle
Es gibt viele gute Gründe, i <7 zu schreiben. Es ist gut, die Nummer 7 in einer Schleife zu haben, die sieben Mal wiederholt wird. Die Leistung ist praktisch identisch. Fast jeder schreibt i <7. Wenn Sie aus Gründen der Lesbarkeit schreiben, verwenden Sie das Formular, das jeder sofort erkennt.
quelle
Ich habe es immer vorgezogen:
quelle
Wenn Sie sich angewöhnen, <zu verwenden, wird dies sowohl für Sie als auch für den Leser konsistent, wenn Sie ein Array durchlaufen. Es wird für jeden einfacher sein, eine Standardkonvention zu haben. Und wenn Sie eine Sprache mit 0-basierten Arrays verwenden, ist <die Konvention.
Dies ist mit ziemlicher Sicherheit wichtiger als jeder Leistungsunterschied zwischen <und <=. Streben Sie zuerst nach Funktionalität und Lesbarkeit und optimieren Sie dann.
Ein weiterer Hinweis ist, dass es besser wäre, die Gewohnheit zu haben, ++ i zu machen, als i ++, da Abrufen und Inkrementieren ein temporäres und Inkrementieren und Abrufen nicht erfordert. Für Ganzzahlen optimiert Ihr Compiler wahrscheinlich die temporäre Abwesenheit, aber wenn Ihr iterierender Typ komplexer ist, kann er dies möglicherweise nicht.
quelle
Verwenden Sie keine magischen Zahlen.
Warum ist es 7? (oder 6 für diese Angelegenheit).
Verwenden Sie das richtige Symbol für die Nummer, die Sie verwenden möchten ...
In diesem Fall denke ich, ist es besser zu verwenden
quelle
Die Operatoren '<' und '<=' sind genau die gleichen Leistungskosten.
Der Operator '<' ist ein Standardoperator und in einer auf Null basierenden Schleife leichter zu lesen.
Die Verwendung von ++ i anstelle von i ++ verbessert die Leistung in C ++, jedoch nicht in C # - ich weiß nichts über Java.
quelle
Wie die Leute beobachtet haben, gibt es keinen Unterschied zwischen den beiden von Ihnen genannten Alternativen. Um dies zu bestätigen, habe ich ein einfaches Benchmarking in JavaScript durchgeführt.
Sie können die Ergebnisse hier sehen . Was daraus nicht klar ist, ist, dass wenn ich die Position des 1. und 2. Tests tausche, die Ergebnisse für diese 2 Tests tauschen, dies eindeutig ein Speicherproblem ist. Der dritte Test, bei dem ich die Reihenfolge der Iteration umkehre, ist jedoch deutlich schneller.
quelle
Wie jeder sagt, ist es üblich, 0-indizierte Iteratoren auch für Dinge außerhalb von Arrays zu verwenden. Wenn alles bei beginnt
0
und endetn-1
und Untergrenzen immer<=
und Obergrenzen immer<
sind, müssen Sie beim Überprüfen des Codes viel weniger nachdenken.quelle
Gute Frage. Meine Antwort: Verwenden Sie Typ A ('<')
i < strlen(s)
als den Index des letzten Elements, daher ist die Einheitlichkeit wichtig.Ein weiteres Problem ist mit diesem ganzen Konstrukt.
i
erscheint dreimal darin, so dass es falsch geschrieben werden kann. Das for-loop-Konstrukt sagt, wie zu tun ist, anstatt was zu tun ist . Ich schlage vor, dies zu übernehmen:BOOST_FOREACH(i, IntegerInterval(0,7))
Dies ist klarer, kompiliert genau die gleichen Anweisungen usw. Fragen Sie mich nach dem Code von IntegerInterval, wenn Sie möchten.
quelle
So viele Antworten ... aber ich glaube, ich habe etwas hinzuzufügen.
Ich bevorzuge, dass die Literalzahlen klar zeigen, welche Werte "i" in der Schleife annehmen . Im Fall der Iteration durch ein nullbasiertes Array:
for (int i = 0; i <= array.Length - 1; ++i)
Und wenn Sie nur eine Schleife ausführen und nicht durch ein Array iterieren, ist das Zählen von 1 bis 7 ziemlich intuitiv:
for (int i = 1; i <= 7; ++i)
Die Lesbarkeit übertrifft die Leistung, bis Sie sie profilieren, da Sie wahrscheinlich nicht wissen, was der Compiler oder die Laufzeit bis dahin mit Ihrem Code tun wird.
quelle
Sie können
!=
stattdessen auch verwenden . Auf diese Weise erhalten Sie eine Endlosschleife, wenn Sie einen Fehler bei der Initialisierung machen, wodurch der Fehler früher bemerkt wird und alle Probleme, die dadurch verursacht werden, darauf beschränkt sind, in der Schleife hängen zu bleiben (anstatt ein Problem viel später zu haben und nicht zu finden es).quelle
Ich denke, beide sind in Ordnung, aber wenn Sie sich entschieden haben, bleiben Sie bei dem einen oder anderen. Wenn Sie es gewohnt sind, <= zu verwenden, versuchen Sie, <nicht zu verwenden und umgekehrt.
Ich bevorzuge <=, aber in Situationen, in denen Sie mit Indizes arbeiten, die bei Null beginnen, würde ich wahrscheinlich versuchen, <zu verwenden. Es ist jedoch alles persönliche Präferenz.
quelle
Streng genommen muss man denken, dass
< count
dies effizienter wäre als<= count
aus dem genauen Grund, aus dem<=
auch die Gleichstellung geprüft wird.quelle