Test Schleifen an den oberen oder unteren? (while vs. do while)
Wenn ich unter CS im college (Mitte der 80er), eine der Ideen, die sich ständig wiederholte, war zu schreiben immer Schleifen, die Prüfung an der Spitze (während...), anstatt am unteren Rand (do ... while) der Schleife. Diese Begriffe wurden oft gesichert mit verweisen auf Studien, die zeigten, dass Schleifen, die getestet an der Spitze waren statistisch viel wahrscheinlicher, korrekt zu sein, als Ihr Boden-Test-Pendants.
Folge, dass ich fast immer schreiben Schleifen, die den test an der Spitze. Ich Tue es nicht, wenn es führt zusätzliche Komplexität im code, aber in diesem Fall scheint selten. Ich merke, dass einige Programmierer neigen dazu, fast ausschließlich schreib-Schleifen-test auf der Unterseite. Wenn ich sehe, Konstrukte wie:
if (condition)
{
do
{
...
} while (same condition);
}
oder die inverse (if
innerhalb der while
), es macht mich Frage mich, ob Sie tatsächlich schrieb, dass es der Weg oder wenn Sie Hinzugefügt, die if
- Anweisung, wenn Sie realisierten, dass die Schleife gar nicht mit den null-Fall.
Habe ich getan einige googeln, aber nicht in der Lage zu finden keine Literatur zu diesem Thema. Wie könnt Ihr Jungs (und Mädels) schreiben Sie Ihre loops?
- "statistisch viel wahrscheinlicher, korrekt zu sein:" Vergessen Sie die Statistik. Den Nachweis, ein top-of-the-loop-Bedingung ist einfach. Der Nachweis eines bottom-of-the-loop-Zustand ist sehr viel komplexer.
- Verwandte Frage: stackoverflow.com/questions/224138/infinite-loops-top-or-bottom
- Ich hatte ein CS-professor circa 1997 zu verkünden, dass Ihr zwei Möglichkeiten in der Programmierung waren C oder Pascal, und, dass Sie wählen sollten, Pascal, weil es nicht lassen Sie increment loop-Zähler aus der Schleife. Er könnte Recht gehabt haben, aber junge war er falsch.
- RE "statistisch wahrscheinlicher, korrekt zu sein": Die Tatsache, dass etwas ist in der REGEL die richtige Antwort bedeutet nicht, es ist IMMER die richtige Antwort. Eines der am meisten repetively frustrierend Dinge, die ich dort finde, ist, dass einige intelligente person wird sagen, "X stellte sich heraus, um eine gute Lösung für viele Probleme", und dann ein paar andere Leute werden sagen: "Unser standard ist X. Sie müssen immer mit X, alle Probleme zu lösen." Wie, das Web ist eine großartige Lösung für viele Probleme. Aber eine Organisation, für die ich arbeitete beschlossen, dass daher ALLE neuen Anwendungen muss web-basiert.
- Ich denke, die Implikation war, dass Sie eher die Einführung einer loop-Grenze Fehler über eine Boden-Tests-Schleife und sollte daher darauf achten, dass es die beste Art ist, um auszudrücken, einen Algorithmus. Nicht-verbieten Sie geradezu.
- Okay. Wenn der Punkt ist der: die Programmierer Schraube bis DO/WHILEs oft mehr, als Sie es vermasseln Vanille WHILESs. Ich nehme an, es ist plausibel, dass Programmierer, die denken, Sie bekommen ein flag innerhalb einer DO/WHILE, wenn Sie wirklich nicht, während es weniger wahrscheinlich, um nicht über eine gültige Prüfung in einer Ebene WÄHREND. Ich bin mir nicht sicher, welchen Schluss Sie daraus ziehen, dass. Vorsichtiger sein, wenn dabei das TUN?
- Kommen Sie, daran zu denken, ich habe noch nie gesehen, die do/while-in Produktion code.
- VIELE Duplikate dieser Debatte: stackoverflow.com/questions/224059/..., stackoverflow.com/questions/390605/while-vs-do-while stackoverflow.com/questions/1035229/..., stackoverflow.com/questions/3094972/..., etc.
- Oops. Ich habe Suche. Nicht zu gut, so scheint es.
- Wow, das ist ein perfektes Beispiel, warum nicht exakten Duplikate dürfen nicht zusammengeführt werden. Sieht aus wie die Hälfte der Antworten sind ursprünglich gegeben worden ist, zu einer völlig anderen Frage, die entlang der Linien von "was ist der Unterschied". Ich fast downvoted einige von Ihnen, bevor ich realisiert es ist nicht die Antwort, die verdienen einen Ruf zu verlieren, aber der übereifrige moderator wer hat ganz gute Antworten und bewegt Sie, um eine unabhängige Frage, die Sie nicht beheben.
- Was Konstrukt ist "statistisch wahrscheinlicher, korrekt zu sein" ist eine bizarre Kriterium. Was zählt, ist, "Was ist richtig für dieses spezielle problem?" Statistisch gesehen, den wir hinzufügen möchten, die mehr als oft wollen wir multiplizieren. Würden Sie deshalb sagen, dass jede Zeit, die Sie brauchen, zu rechnen, sollten Sie immer mit "+" und verwenden Sie niemals "*" da, "statistisch", dass Sie oft korrigieren hinzufügen? Oder, ich gehe in das Lebensmittelgeschäft mehr oft, dass ich das Auto dem Händler, daher jedes mal, wenn ich das Haus verlasse werde ich automatisch in den Supermarkt gehen-auch wenn das, was ich tun möchte, ist ein neues Auto kaufen.
- Ich benutze do-while-Schleifen die ganze Zeit im optimierten code. Sie haben den Vorteil der Reduzierung der Maschine, code-Größe, indem Sie nicht duplizieren, die loop-check (hab ich oft gesehen-Reduktionen von 20% oder mehr) und die Verringerung der code-cache-Fuß drucken. Sie können prüfen, Wiederaufnahme dieser, so kann ich die post eine Antwort?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich immer an die Regel, dass, wenn es laufen soll, null oder mehrere Male, Prüfung am Anfang, ob es ausgeführt werden muss einmal oder mehr, test am Ende. Ich sehe keinen logischen Grund für die Verwendung von code, die Sie aufgelistet, die in deinem Beispiel. Es erhöht nur die Komplexität.
Verwenden Sie while-Schleifen, wenn Sie testen möchten, ein Zustand vor der ersten iteration der Schleife.
Verwenden Sie die do-while-Schleifen, wenn Sie testen möchten, eine Bedingung nach der Ausführung der ersten iteration der Schleife.
Zum Beispiel, wenn Sie finden, sich selbst etwas zu tun wie diese beiden snippets:
Sollten Sie umschreiben es so:
condition
überprüfenUnterschied ist, dass die do-Schleife ausführt, "etwas tun" einmal und dann die Bedingung überprüft, um zu sehen, ob es sich wiederholen soll, die "etwas tun", während die while-Schleife prüft die Bedingung, bevor Sie etwas
Nicht.
Ob es mehr Sinn macht die Verwendung einer
do
/while
Schleife, dann tun Sie das. Wenn Sie ausführen müssen, der Körper der Schleife einmal vor dem testen der Bedingung, dann eindo
/while
Schleife ist wahrscheinlich die einfachste Implementierung.Ersten kann man nicht ausführen, wenn Bedingung falsch ist. Andere wird mindestens einmal ausgeführt, dann überprüfen Sie die conidition.
Gründen der Lesbarkeit scheint es sinnvoll zu testen, an der Spitze. Die Tatsache, dass es eine Schleife ist wichtig, die person, die Lektüre der code sollte sich bewusst sein, der loop-Bedingungen, bevor Sie versuchen zu begreifen, die Körper der Schleife.
do {} while ()
, wenn es einen kurzen code-block.Hier ein gutes Beispiel aus der Praxis, ich kam in jüngster Zeit. Angenommen, Sie haben eine Reihe von Verarbeitungs-Aufgaben (wie die Bearbeitung von Elementen in einem array) und Sie möchten, teilen Sie die Arbeit zwischen einem thread pro CPU-Kern vorhanden ist. Es muss mindestens ein core läuft, den aktuellen code! So können Sie eine
do... while
etwas wie:Es ist fast negligable, aber es könnte sich lohnen, in Anbetracht der performance-Vorteil: es könnte genauso geschrieben werden wie ein standard -
while
Schleife, das würde aber immer eine unnötige Erster Vergleich würde immer zu bewertentrue
- und auf single-core -, die do-while-Bedingung Filialen und mehr vorhersehbar (immer false, versus abwechselnd true/false-standardwhile
).Ersten tests, die den Zustand vor der Ausführung, so ist es möglich, Ihren code nicht immer den code eingeben, der darunter. Die zweite durchführen wird der code vor dem testen der Bedingung.
Die while-Schleife überprüfen "Zustand" Erstens; wenn es false ist, wird es nie "etwas zu tun." Aber die do...while-Schleife wird "etwas tun" zuerst, dann überprüfen Sie "Zustand".
Yaa..es ist wahr.. tun, während Sie laufen mindestens ein mal.
Das ist der einzige Unterschied. Nichts anderes zu Debatte über diese
Ja, genauso wie mit für anstelle von while-oder foreach-statt für die Lesbarkeit verbessert. Sagte, dass einige Situationen tun müssen, aber ich Stimmen Sie wäre dumm, zu zwingen, diese Situationen in eine while-Schleife.
Es ist mehr hilfreich, um das denken in Bezug auf die gemeinsame Nutzung. Die überwiegende Mehrheit der while-Schleifen arbeiten ganz selbstverständlich mit
while
, auch wenn Sie gemacht werden könnte, um die Arbeit mitdo...while
, also im Grunde sollten Sie verwenden, wenn die Differenz egal ist. Ich würde sodo...while
für die seltene Szenarien, wo es bietet eine deutliche Verbesserung der Lesbarkeit.Die Anwendungsfälle sind unterschiedlich für die beiden. Dies ist keine "best practices" in Frage.
Wenn Sie möchten, eine Schleife ausführen, basierend auf der Bedingung, die ausschließlich als
für oder während
Wenn Sie etwas tun wollen einmal unabhängig von der der Zustand, und dann auch weiterhin tun es auf der Grundlage der Zustandsbewertung.
do..while -
Einen while () - prüft die Bedingung vor jeder Ausführung der Schleife und ein do...while() prüft die Bedingung nach jeder Ausführung der Schleife Körper.
So, **do...while()**s wird immer führen Sie die Schleife wenigstens einmal.
Funktional eine while() ist äquivalent zu
- und einer do...while() ist äquivalent zu
Beachten Sie, dass die Umsetzung ist wahrscheinlich effizienter als diese. Jedoch, eine do...while() erfordert einen Vergleich weniger als eine while () - so ist es etwas schneller. Verwenden Sie eine do...while() wenn:
Hier ist die übersetzung:
Gleiche wie
Beachten Sie die zusätzlichen Satz von Klammern für den Fall, Sie haben Variablen-Definitionen in
y
. Der Umfang dieser muss gehalten werden lokale wie in der do-loop-Fall. So, eine do-while-Schleife wird nur ausgeführt, seinen Körper mindestens einmal. Abgesehen davon, dass die beiden Schlaufen identisch sind. Also, wenn wir diese Regel anwenden, um Ihren codeDen entsprechenden while-Schleife für Ihre do-Schleife sieht wie
Ja, Sie finden die entsprechenden, während Sie für Ihre do-Schleife unterscheidet sich von Ihr, während 🙂
Ich Neige dazu, lieber do-while-Schleifen, mich. Wenn die Bedingung immer werden wahr am Anfang der Schleife, die ich bevorzuge, um es zu testen am Ende. Zu meinem Auge, der ganze Sinn der Test-Bedingungen (andere als Behauptungen) ist, dass man nicht wissen, das Ergebnis des Tests. Wenn ich sehe, dass eine while-Schleife mit der Bedingung test an der Spitze, meine Neigung ist, betrachten wir den Fall, dass die Schleife null mal. Wenn das nie passieren kann, warum nicht code in einer Weise, die deutlich zeigt, dass?
Ist es eigentlich für unterschiedliche Dinge. In C verwenden, können Sie do - while - Konstrukt sowohl in Szenario (mindestens einmal ausgeführt wird und ausgeführt wird, während true). Aber PASCAL hat repeat - until und während für jedes Szenario und wenn ich mich richtig erinnere, ADA hat ein anderes Konstrukt, das können Sie beenden Sie in der Mitte, aber das ist natürlich nicht das, was Sie gefragt haben.
Meine Antwort zu deiner Frage : ich mag meine Schleife mit der Prüfung an der Spitze.
Für alle, die nicht denken, ein Grund, um eine ein-oder-mehr-mal-Schleife:
Das gleiche kann verwendet werden für jede Art von hierarchischer Struktur.
in der Klasse Knoten:
Beide Konventionen sind die richtigen, wenn Sie wissen, wie zu schreiben der code korrekt 🙂
In der Regel die Verwendung der zweiten Konvention ( do {} while() ) gemeint ist, zu vermeiden, haben einen doppelten Anweisung außerhalb der Schleife. Betrachten Sie das folgende (stark vereinfacht) Beispiel:
geschrieben werden können, mehr bündig mit
Natürlich, in diesem bestimmten Beispiel kann geschrieben werden, in noch übersichtlicherer Weise als (vorausgesetzt, C-syntax)
Aber ich glaube, Ihr seht den Punkt hier.
Wie bereits von Piemasons, der Unterschied ist, ob die Schleife einmal ausgeführt, bevor Sie den test, oder wenn der test zuerst gemacht, so dass der Körper der Schleife möglicherweise nie ausgeführt.
Entscheidend ist die Frage, die Sinn macht für Ihre Anwendung.
Nehmen wir zwei einfache Beispiele:
Sagen, du bist einer Schleife durch die Elemente in einem array. Wenn das array hat keine Elemente, die Sie nicht wollen, um Prozess Nummer-eins-null. Benutzen Sie deshalb WÄHREND.
Sie eine Meldung anzeigen möchten, akzeptieren Sie eine Antwort, und falls die Antwort ungültig ist, wieder Fragen, bis Sie eine gültige Antwort. So möchte man immer mal Fragen. Sie können nicht testen, ob die Antwort gültig ist, bis Sie eine Antwort bekommen, so, Sie gehen durch den Körper der Schleife einmal, bevor Sie zum testen der Bedingung. Sollten Sie verwenden eine DO/WHILE.
Ich Schreibe mir so ziemlich ausschließlich Test an der Spitze. Es ist weniger code, also für mich zumindest, es ist weniger Potenzial, um die Schraube etwas (z.B., copy & Paste dieser Zustand lässt zwei Orte, die Sie immer haben, zu aktualisieren)
Es hängt wirklich es gibt Situationen, wenn Sie testen wollen, an der Spitze, andere, wenn Sie testen möchten, auf der Unterseite, und noch andere, wenn Sie möchten, testen Sie in der Mitte.
Aber das Beispiel scheint absurd. Wenn Sie gehen, um zu testen, an der Spitze, nicht mit einer if-Anweisung und testen Sie an der Unterseite, verwenden Sie einfach eine while-Anweisung, das ist, was es gemacht ist.
Sollten Sie zuerst denken, der den test als Teil der code der Schleife. Wenn der test logischerweise gehört, an den start des loop-Verarbeitung, dann ist es ein top-of-the-loop-test. Wenn der test logischerweise gehört am Ende der Schleife (d.h. er entscheidet, ob die Schleife weiter ausgeführt), dann ist es wahrscheinlich ein bottom-of-the-loop-test.
Haben Sie zu tun, etwas ausgefallenes, wenn der test logischerweise gehört in diese Mitte. 🙂
Ich denke, einige Leute testen am Boden, weil Sie sparen können eine oder wenige Maschinen-Zyklen zu tun, die vor 30 Jahren.
Code zu schreiben, der korrekt ist, man im Grunde braucht, um eine geistige, vielleicht informeller Nachweis der Korrektheit.
Zu beweisen, dass eine Schleife korrekt ist, ist der standard-Weg ist zu wählen, ein loop-invariant, und eine Induktion Beweis. Aber überspringen Sie die komplizierten Worte: was Sie tun, informell, ist herauszufinden, etwas, das ist wahr jeder iteration der Schleife, und wenn die Schleife fertig ist, was Sie wollte, erreicht, ist nun wahr. Der loop-invariant ist falsch, am Ende, für die Schleife zu beenden.
Wenn die loop-Bedingungen anzeigen ziemlich leicht, um die Invarianten und die invariante ist an den Anfang der Schleife, und man folgert, dass die invariante wahr ist, bei der nächsten iteration der Schleife durch die Arbeit durch den code der Schleife, dann ist es einfach, um herauszufinden, dass die Schleife korrekt ist.
Jedoch, wenn die invariante am Ende der Schleife, dann, es sei denn, Sie haben eine Behauptung nur vor der Schleife (gute Praxis), dann wird es schwieriger, da Sie im wesentlichen ableiten, welche, die unveränderlich sein sollte, und dass jeder code ausgeführt, bevor die Schleife wird die Schleife invariante true (da ist keine Schleife Bedingung ist, dass code ausgeführt wird, der in der Schleife). Es wird einfach, dass die noch schwieriger zu beweisen richtig ist, auch wenn es eine informelle in-your-head Beweis.
Ist dies nicht wirklich eine Antwort, aber eine Wiederholung von etwas, einer meiner Dozenten sagte-und es Interessierte mich zu der Zeit.
Den zwei Arten von loop while..do und do..while sind eigentlich Instanzen ein Drittel mehr generische Schleife, die den test irgendwo in der Mitte.
Code-block A wird mindestens einmal ausgeführt und B ausgeführt wird, null oder mehrere Male, jedoch ist nicht ausgeführt, auf der letzten (fehlerhaften) iteration. eine while-Schleife, wenn der code-block eine leer-und eine do..while ist, wenn ein code-block b ist leer. Aber wenn Sie das schreiben eines Compilers, die Sie interessieren könnten Verallgemeinerung beiden Fällen zu einer Schleife wie diesem.
Der Unterschied ist offensichtlich und ermöglicht es Ihnen, code ausführen und bewerten Sie dann das Ergebnis zu sehen, wenn Sie "es wieder Tun" und die andere Methode, während ermöglicht es Ihnen, einen block von Skript ignoriert, wenn die Bedingung nicht erfüllt ist.
In eine typische Diskrete Strukturen-Klasse in der informatik, ist es eine einfache Beweis dafür, dass es eine äquivalenz-Zuordnung zwischen den beiden.
Stilistisch bevorzuge ich zwar (leicht-expr) { } wenn easy-expr bekannt ist vorne und bereit zu gehen, und die Schleife wird nicht viel wiederholt, overhead/Initialisierung. Ich bevorzuge do { } while (etwas-weniger-easy-expr); wenn es mehr wiederholt overhead und der Zustand vielleicht nicht ganz so einfach einzurichten, vor der Zeit. Wenn ich Schreibe, eine unendliche Schleife ich immer mit while (true) { }. Ich kann nicht erklären warum, aber ich mag nicht schreiben for (;;) { }.
Ich würde sagen, es ist eine schlechte Praxis zu schreiben, wenn..do..while-Schleifen, aus dem einfachen Grund, dass dies erhöht die Größe der code-und Ursachen-code-Duplikationen. Code-Duplikationen sind fehleranfällig und sollte vermieden werden, da jede änderung an einem Teil muss durchgeführt werden, auf das doppelte, was nicht immer der Fall. Auch, größer-code bedeutet, dass eine härtere Zeit auf die cpu-cache. Schließlich behandelt null-Fällen, und löst Kopfschmerzen.
Nur bei der ersten Schleife ist grundlegend sollte man verwenden, do..while, sagen wir, wenn der code, der lässt Sie passieren die Schleifenbedingung (wie Initialisierung) durchgeführt wird, in der Schleife. Ansonsten, wenn es sicher ist, dass die Schleife wird nie fallen bei der ersten iteration, dann ja, eine do..while-geeignet ist.
Aus meiner begrenzten Kenntnis des code generation ich denke, es kann eine gute Idee sein, zu schreiben, Boden-test-Schleifen, da Sie ermöglichen, die der compiler durchführen-loop Optimierungen besser. Für Boden-test-Schleifen es wird garantiert, dass die Schleife mindestens einmal ausgeführt wird. Dies bedeutet, loop-invariant code "beherrscht" den Ausfahrt Knoten. Und so sicher verschoben werden können, kurz bevor die Schleife beginnt.
In der Regel, es hängt davon ab, wie Sie Ihren code strukturieren. Und wie schon jemand beantwortet, einige algorithmen benötigen mindestens eine iteration durchgeführt. So, zu entkommen, zusätzliche iteration-count "oder" at-least-one-interation-aufgetreten, die Flagge, die Sie beschäftigen, do/while.