Für welchen Wert von i ist, während (i == i + 1) {} Schleife für immer?
Betrachten die folgende Schleife, in der ich ist, bisher nicht deklarierte:
while (i == i + 1) {}
Finden Sie die definition von i
vor dieser Schleife, so dass die while-Schleife
Fort für immer.
Die nächste Frage, die sich die gleiche Frage gestellt für dieses code-snippet:
while (i != i) {}
war mir klar. Natürlich, in dieser anderen situation ist es NaN
aber ich bin wirklich fest auf dem vorherigen. Hat das zu tun mit überlauf? Was würde dazu führen, eine solche Schleife, um für immer in Java?
- Alle Möglichkeiten zu überschreiben
.equals()
Methode? Da ich nicht deklarierten, können wir jede Klasse, was wir wollen. - Das ist die Frage, was soll
i
werden, um es in eine Endlosschleife. - aber der code nicht verwenden
.equals
. Und==
NICHT immer aufrufen.equals
- Ich bin mit einem von algorithmen seminar, und ich bin beauftragt mit der Suche nach Debuggen von Problemen für Schüler und Studenten. Ich rannte über dieses problem und wurde neugierig.
- das Studium "unprofessionell" code lässt du mehr "professionelle", also... Eh, das ist eine gute Frage
- In C, int i = INT_MAX; könnte möglicherweise auch in einer Endlosschleife landen, sondern in Java-überlauf voll definiert Verhalten und würde beenden die Schleife.
- Während ich sehe, wie kann man fasziniert sein von so eine Frage für eine sofortige (zum Spaß), ich scheitern zu sehen, wie es einen gültigen Platz in der sogenannten "Advanced Programming Exam". Die gleiche Prüfung heißt es: "Stil ist entscheidend: Sie kann erhalten mehr Kredit für eine Vorlage mit gut strukturierten code". Ich meine, du hast zu verarschen. WTF, professor, WTF? Sie Rauchen Unkraut wieder?
- Ich vermute, dieser professor hat unterzogen wurde, um viele Jahre grading code von Studenten, die können nicht buchstabieren "strukturiert", viel weniger code mit der Struktur. Dies kann nur seine Art der Belohnung Studenten, die sich die Zeit nehmen, um code übersichtlich.
- Fun fact, in C# funktioniert das auch für null-Werte zulässt numerische Typen, deren Werte
null
, danull == null
ist wahr, undnull + 1
istnull
. - die Beurteilung durch die sehr große Anzahl von Fragen auf, SO dass die letztlich nach unten kommen, um ein scheitern zu verstehen, die Eigenschaften der "floating-point Arithmetik" (darunter, nicht zu wissen, warum
0.2 * 5 != 1.0
) ich glaube, dass offenbar (und leider) in der heutigen Welt 1) zu wissen, wie "floating point Arithmetik" arbeitet "advanced programming" und 2) es ist das wissen auch bitter nötig, durch viele, viele Programmierer arbeiten. 0.2 * 5
scheint genau1.0
in C/Java/Python/Ruby.0.2 + 0.1 != 0.3
scheint, gilt für alle diese Sprachen, obwohl.- Die situation ist viel schlimmer als Sie sich vorstellen. In vielen Sprachen, die floating point Arithmetik getan werden muss, zumindest in der 64 bit Genauigkeit angegeben durch ein double, was bedeutet, dass es getan werden kann, in der höheren Präzision bei der Laune des Compilers, und in der Praxis geschieht dies. Ich kann Sie in einem Dutzend Fragen, die auf dieser Website von C# - Programmierer, die Fragen, warum
0.2 + 0.1 == 0.3
ändert seinen Wert je nach compiler-Einstellungen, die phase des Mondes, und so weiter. - Die Schuld für dieses Chaos fällt auf Intel, die gab uns einen Chipsatz, der hat eine höhere Präzision und schnellere Gleitkomma-Arithmetik ob die zahlen können sich registrierte, was bedeutet, dass die Ergebnisse einer Fließkomma-Berechnung können deren Werte ändern, je nachdem, wie gut der register-Planer, der Optimierer arbeitet heute. Ihre Entscheidungen, wie eine Sprache, die designer sind dann zwischen wiederholbare Berechnungen und die schnelle, präzise Berechnungen, und die Gemeinschaft, kümmert sich um die Gleitkomma-Mathematik wird für das letztere zu entscheiden.
- Mögliche Duplikate von Endlos-for-Schleife mit float
- Ich weiß nicht wirklich sehen, wie dies ist ein doppelter von post. Das problem, das ich präsentiert wird, ist allgemeiner als die Macken des IEEE 754 standard. Dieser Beitrag soll auch für C# - und .NET, die haben Ihre eigenen Macken, im Gegensatz zu Java-wie andere Kommentatoren erwähnt haben, in diesem post.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vor allem, da die
while (i == i + 1) {}
Schleife nicht ändern, den Wert voni
, so dass diese Schleife unendlich äquivalent ist zu der Wahl einen Wert voni
erfüllt, dassi == i + 1
.Gibt es viele solche Werte:
Beginnen wir mit den "exotischen" Sachen:
oder
Der Grund für diese Werte befriedigend
i == i + 1
angegeben ist-inJLS 15.18.2. Additive Operatoren (+ und -) für Numerische Datentypen:
Dies ist nicht verwunderlich, da das hinzufügen einer endlichen Wert zu einem unendlichen Wert führen sollte, in einen unendlichen Wert.
Sagte, die meisten der Werte von
i
erfülleni == i + 1
sind einfach großedouble
(oderfloat
) Werte:Beispiel:
oder
oder
Den
double
undfloat
Arten haben nur begrenzte Genauigkeit, so dass, wenn Sie nehmen eine ausreichend großedouble
oderfloat
Wert hinzufügen1
es führt zum gleichen Wert.(double)(1L<<53)
-- oderfloat i = (float)(1<<24)
double i = 9007199254740992L;
(oder...94L
oder...96L
., etc.), da Sie mit einerdouble
,9007199254740992 + 1
ist9007199254740992
, da die floating-point-Ungenauigkeit, äußert sich auf die gesamte Anzahl Dezimalstellen für eine Zahl, die groß ist.inf = inf
ist undefiniert, in jedem system, das ich denken kann aus der Spitze von meinem Hut.Diese Rätsel sind im detail beschrieben in "Java Teilnehmer: Traps, Pitfalls, and Corner Cases" Buch von Joshua Bloch und Neal Gafter.
oder:
beide führen in eine Endlosschleife, da das hinzufügen
1
zu einem Fließkomma-Wert, der ausreichend groß ist, wird nicht den Wert ändern, weil es nicht "die Lücke" zu seinem Nachfolger1.Einen Hinweis über die zweite puzzle (für zukünftige Leser):
führt auch in eine Endlosschleife, weil NaN ist ungleich jeder floating-point-Wert, inklusive sich selbst 2.
1 - Java-Teilnehmer: Traps, Pitfalls, and Corner Cases (Kapitel 4 - Loopy Teilnehmer).
2 - JLS §15.21.1
Nur eine Idee: was ist boolesch?
Ist das nicht ein Fall, wo
i + 1 == i
?+
Betreiber, das dauert einboolean
und einint
als Operanden).double i = Double.POSITIVE_INFINITY;