Ich habe meinen Schülern erklärt, dass Gleichheitstests für Float-Variablen nicht zuverlässig sind, aber für ganze Zahlen in Ordnung sind. Das Lehrbuch, das ich benutze, besagt, dass es einfacher ist,> und <als> = und <= zu lesen. Ich stimme einigermaßen zu, aber in einer For-Schleife? Ist es nicht klarer, wenn die Schleife den Start- und den Endwert angibt?
Vermisse ich etwas, worüber der Autor des Lehrbuchs korrekt ist?
Ein weiteres Beispiel sind Reichweitentests wie:
wenn Punktzahl> 89 Note = 'A'
sonst wenn Punktzahl> 79 Note = 'B' ...
Warum nicht einfach sagen: wenn Score> = 90?
Antworten:
In geschweiften Programmiersprachen mit nullbasierten Arrays ist es üblich,
for
Schleifen wie folgt zu schreiben :Dies durchläuft alle Elemente im Array und ist bei weitem der häufigste Fall. Es vermeidet die Verwendung von
<=
oder>=
.Dies müsste sich nur ändern, wenn Sie das erste oder letzte Element überspringen oder in die entgegengesetzte Richtung oder von einem anderen Startpunkt zu einem anderen Endpunkt bewegen müssen.
Für Sammlungen in Sprachen, die Iteratoren unterstützen, ist Folgendes üblicher:
Das vermeidet die Vergleiche gänzlich.
Wenn Sie nach einer festen Regel für die Verwendung von
<=
vs suchen<
, gibt es keine. Verwenden Sie, was Ihre Absicht am besten ausdrückt. Wenn Ihr Code das Konzept "Weniger als oder gleich 55 Meilen pro Stunde" ausdrücken muss,<=
muss dies nicht heißen<
.Die Beantwortung Ihrer Frage zu den Notenbereichen
>= 90
ist sinnvoller, da 90 der tatsächliche Grenzwert ist und nicht 89.quelle
for
solche Schleifen sind. Die Form derfor
Schleife, die ich hier zur Verfügung gestellt habe, ist für jeden Entwickler mit ein wenig Erfahrung sofort erkennbar. Wenn Sie eine spezifischere Antwort basierend auf einem spezifischeren Szenario wünschen, müssen Sie dies in Ihre Frage aufnehmen.Es spielt keine Rolle.
Aber aus Gründen der Argumentation, lassen Sie sich die beiden Optionen analysiert:
a > b
vsa >= b
.Abwarten! Das sind nicht gleichbedeutend!
OK, dann
a >= b -1
vsa > b
odera > b
vsa >= b +1
.Hm,
a >b
unda >= b
beide sehen besser aus alsa >= b - 1
unda >= b +1
. Was sind das für alles1
? Also würde ich , dass jeder Vorteil argumentieren aus, die>
statt>=
durch, die addieren oder subtrahieren Zufalls- oder umgekehrt eliminiert1
s.Aber was ist, wenn es eine Zahl ist? Ist es besser zu sagen
a > 7
odera >= 6
? Warte eine Sekunde. Überlegen wir ernsthaft, ob es besser ist , die hartcodierten Variablen mit>
vs zu vergleichen>=
und zu ignorieren? Es wird also wirklich eine Frage, oba > DAYS_OF_WEEK
es besser ist alsa >= DAYS_OF_WEEK_MINUS_ONE
... oder ob esa > NUMBER_OF_LEGS_IN_INSECT_PLUS_ONE
vs ista >= NUMBER_OF_LEGS_IN_INSECT
? Und wir werden wieder1
s addieren / subtrahieren , nur diesmal in Variablennamen. Oder vielleicht darüber nachdenken, ob es am besten ist, Schwelle, Grenze, Maximum zu verwenden.Und es sieht so aus, als gäbe es keine allgemeine Regel: Es kommt darauf an, was verglichen wird
In der Tat gibt es viel wichtigere Dinge, die im eigenen Code verbessert werden müssen, und viel objektivere und vernünftigere Richtlinien (z. B. Begrenzung der X-Zeichen pro Zeile), für die es noch Ausnahmen gibt.
quelle
>
vs>=
oder die Diskussion darüber, ob die Diskussion von>
vs>=
sinnvoll ist? obwohl es wahrscheinlich am besten ist, dies nicht zu diskutieren: pRechnerisch gibt es keinen Unterschied in den Kosten bei der Verwendung
<
oder im>
Vergleich zu<=
oder>=
. Es wird genauso schnell berechnet.Die meisten for-Schleifen werden jedoch von 0 an gezählt (da viele Sprachen für ihre Arrays die Indexierung 0 verwenden). Die kanonische for-Schleife in diesen Sprachen lautet also
Wenn Sie dies mit einem tun,
<=
müssen Sie irgendwo ein -1 hinzufügen, um den Fehler zu vermeiden, bei dem die Abweichung um eins auftrittoder
Wenn die Sprache eine 1-basierte Indizierung verwendet, würden Sie natürlich <= als einschränkende Bedingung verwenden.
Der Schlüssel ist, dass die in der Bedingung ausgedrückten Werte diejenigen aus der Problembeschreibung sind. Es ist sauberer zu lesen
für ein halboffenes Intervall als
und muss rechnen, um zu wissen, dass es keinen möglichen Wert zwischen 19 und 20 gibt
quelle
for(markup = 5; markup <= MAX_MARKUP; ++markup)
. Alles andere würde es überkomplizieren.Ich würde sagen, es geht nicht darum, ob Sie> oder> = verwenden sollten. Es geht darum, alles zu verwenden, was Sie zum Schreiben von aussagekräftigem Code benötigen.
Wenn Sie feststellen, dass Sie einen addieren / subtrahieren müssen, sollten Sie den anderen Operator verwenden. Ich finde, dass gute Dinge passieren, wenn Sie mit einem guten Modell Ihrer Domain beginnen. Dann schreibt sich die Logik von selbst.
Das ist viel ausdrucksvoller als
In anderen Fällen ist der andere Weg vorzuziehen:
Viel besser als
Bitte entschuldigen Sie die "primitive Besessenheit". Natürlich möchten Sie hier einen Velocity- und einen Money-Typ verwenden, aber der Kürze halber habe ich sie weggelassen. Der Punkt ist: Verwenden Sie eine präzisere Version, mit der Sie sich auf das Geschäftsproblem konzentrieren können, das Sie lösen möchten.
quelle
Wie Sie in Ihrer Frage ausgeführt haben, ist das Testen auf Gleichheit mit Float-Variablen nicht zuverlässig.
Gleiches gilt für
<=
und>=
.Für ganzzahlige Typen gibt es jedoch keine derartigen Zuverlässigkeitsprobleme. Meiner Meinung nach drückte der Autor sie aus Meinung zum , welche lesbarer ist.
Ob Sie ihm zustimmen oder nicht, ist natürlich Ihre Meinung.
quelle
<
oder zu verwenden<=
. Wie bereits erwähnt, ist eine FOR-Schleife<
in C-Sprachen sinnvoller. Es gibt andere Anwendungsfälle, die dies begünstigen<=
. Verwenden Sie alle Werkzeuge, die Ihnen zur Verfügung stehen, wann und wo dies angebracht ist.for (unsigned int i = n; i >= 0; i--)
oderfor (unsigned int i = x; i <= y; i++)
wenny
zufälligUINT_MAX
. Ups, diese Schleife für immer.Jede der Beziehungen
<
,<=
,>=
,>
und auch==
und!=
haben ihre Anwendungsfälle für den Vergleich zweier Gleitkommazahlen. Jedes hat eine bestimmte Bedeutung und die entsprechende sollte ausgewählt werden.Ich gebe Beispiele für Fälle, in denen Sie genau diesen Operator für jeden von ihnen möchten. (Beachten Sie jedoch die NaNs.)
f
, die einen Gleitkommawert als Eingabe verwendet. Um Ihre Berechnungen zu beschleunigen, fügen Sie einen Cache mit den zuletzt berechneten Werten hinzu, dh eine Zuordnungx
zu einer Nachschlagetabellef(x)
. Sie wollen wirklich verwenden==
, um die Argumente zu vergleichen.x
? Sie möchten wahrscheinlich verwendenx != 0.0
.x
im Einheitsintervall liegt?(x >= 0.0) && (x < 1.0)
ist der richtige Zustand.d
einer Matrix berechnet und möchten feststellen, ob sie eindeutig ist? Es gibt keinen Grund, etwas anderes als zu verwendend > 0.0
.alpha <= 1.0
.Gleitkomma-Mathematik (im Allgemeinen) ist nicht genau. Das heißt aber nicht, dass Sie es fürchten, als Magie behandeln und zwei Fließkommazahlen nicht immer gleich behandeln sollten, wenn sie innerhalb liegen
1.0E-10
. Wenn Sie dies tun, wird Ihre Mathematik wirklich durchbrochen und es werden alle seltsamen Dinge passieren.x != 0.0
undy
ein endlicher Gleitkommawert ist,y / x
muss er nicht endlich sein. Es kann jedoch von Bedeutung sein, zu wissen, oby / x
die Operation aufgrund eines Überlaufs nicht endlich ist oder ob sie anfangs mathematisch nicht gut definiert war.x
im Einheitsintervall [0, 1) liegt, wäre ich wirklich verärgert, wenn er beim Aufruf mitx == 0.0
oder einen Assertionsfehler auslösen würdex == 1.0 - 1.0E-14
.1.0E-30
, wird nichts gewonnen. Alles, was Sie getan haben, war die Wahrscheinlichkeit zu erhöhen , die falsche Antwort zu geben.alpha
möglicherweise von Rundungsfehlern betroffen und daheralpha <= 1.0
möglicherweise richtig, obwohl der wahre mathematische Wert für den Ausdruck, aus dem eralpha
berechnet wurde, möglicherweise größer als 1 war. Sie können derzeit jedoch möglicherweise nichts dagegen unternehmen.Behandeln Sie Fehler wie immer in der Softwareentwicklung auf der entsprechenden Ebene und nur einmal. Wenn Sie Rundungsfehler in der Reihenfolge hinzufügen
1.0E-10
(dies scheint der magische Wert zu sein, den die meisten Leute verwenden, ich weiß nicht warum), werden Sie bei jedem Vergleich von Gleitkommazahlen bald Fehler in der Reihenfolge von finden1.0E+10
…quelle
Die Art der in einer Schleife verwendeten Bedingung kann die Art der Optimierungen einschränken, die ein Compiler zum Guten oder Schlechten ausführen kann. Zum Beispiel gegeben:
Ein Compiler könnte annehmen, dass die obige Bedingung dazu führen sollte, dass die Schleife nach der n-ten Durchgangsschleife beendet wird, es sei denn, n würde 65535 und die Schleife könnte auf eine andere Weise als um i, das n überschreitet, beendet werden. Wenn diese Bedingungen zutreffen, muss der Compiler Code generieren, der dazu führen würde, dass die Schleife ausgeführt wird, bis etwas anderes als die obige Bedingung dazu führt, dass sie beendet wird.
Wenn die Schleife stattdessen wie folgt geschrieben worden wäre:
Dann könnte ein Compiler sicher davon ausgehen, dass die Schleife niemals mehr als n-mal ausgeführt werden muss und somit effizienteren Code generieren kann.
Beachten Sie, dass ein Überlauf mit signierten Typen unangenehme Folgen haben kann. Gegeben:
Ein Compiler könnte dies folgendermaßen umschreiben:
Eine solche Schleife würde sich identisch zum Original verhalten, wenn in den Berechnungen kein Überlauf auftritt. Sie könnte jedoch auch auf Hardwareplattformen für immer ausgeführt werden, auf denen ein Ganzzahlüberlauf normalerweise eine konsistente Umbruchssemantik aufweist.
quelle