Warum gibt der folgende Code 2147483647 aus, der tatsächliche Wert ist 2147483648?
%Vor%Ich verstehe, dass der maximale positive Wert, den ein int enthalten kann, 2147483647 ist. Warum wird ein Code wie dieser automatisch auf die negative Seite umgebrochen und druckt -2147483648?
%Vor%i ist vom Typ Integer. Wenn das zweite Codebeispiel (Addition von zwei Ganzzahlen) auf die negative Seite umbrechen kann, wenn das Ergebnis außerhalb des positiven Bereichs liegt, warum kann die erste Stichprobe nicht umbrochen werden? Auch,
%Vor%was dem zweiten Codebeispiel sehr ähnlich ist, löst einen Kompilierungsfehler aus, der besagt, dass das erste Literal außerhalb des Ganzzahlbereichs liegt? Meine Frage ist, wie im zweiten Codebeispiel, warum kann das erste und dritte Beispiel nicht automatisch auf die andere Seite übertragen werden?
Beim ersten Codebeispiel wird das Ergebnis von double
auf int
eingeschränkt. Die JLS 5.1.3 beschreibt, wie sich die Conversions für Double-Ints verringern durchgeführt.
Der relevante Teil ist:
Der Wert muss zu groß sein (a positiver Wert großer Größe oder positive Unendlichkeit) und das Ergebnis von Der erste Schritt ist der größte darstellbarer Wert vom Typ int oder lang.
Deshalb wird 2 ^ 31 (2147483648) auf Integer.MAX_VALUE (2147483647) reduziert. Das gleiche gilt für
%Vor%und
%Vor%Wenn die Addition wie im zweiten Beispiel ohne Klammern erfolgt, handelt es sich um eine ganzzahlige Addition. Integrale Typen verwenden Zweierkomplement , um Werte darzustellen. Unter diesem Schema fügen Sie 1 zu
hinzu %Vor%gibt
%Vor%Welches ist das Zweierkomplement für -2147483648. Einige Sprachen führen eine Überlaufprüfung für arithmetische Operationen durch (z.B. wirft Ada eine Ausnahme). Java mit seinem C-Erbe prüft nicht auf Überlauf. CPUs setzen typischerweise ein Überlauf-Flag , wenn eine arithmetische Operation über- oder unterläuft. Sprachlaufzeiten können dieses Flag überprüfen, obwohl dies zusätzlichen Overhead verursacht, den manche für unnötig halten.
Das dritte Beispiel wird nicht kompiliert, da der Compiler Literalwerte auf den Bereich ihres Typs überprüft und bei Werten außerhalb des Bereichs einen Compilerfehler angibt. Siehe JLS 3.10.1 - Ganzzahlige Literale .
>Warum springt ein Code wie dieser automatisch auf die negative Seite und druckt -2147483648?
Dies wird Überlauf genannt. Java macht es, weil C es tut. C tut es, weil die meisten Prozessoren es tun. In manchen Sprachen passiert das nicht. Zum Beispiel werden einige Sprachen eine Ausnahme auslösen, in anderen ändert sich der Typ in etwas, das das Ergebnis enthalten kann.
Meine Frage ist, wie im zweiten Codebeispiel, warum kann das erste und dritte Beispiel nicht automatisch auf die andere Seite übertragen werden?
Bezüglich des ersten Programms: Math.pow gibt ein Double zurück und läuft nicht über. Wenn das Double in eine ganze Zahl konvertiert wird, wird es abgeschnitten.
Was Ihr drittes Programm betrifft: Überlauf ist selten eine wünschenswerte Eigenschaft und oft ein Zeichen dafür, dass Ihr Programm nicht mehr funktioniert. Wenn der Compiler erkennt, dass er einen Überlauf erhält, nur weil er eine Konstante auswertet, die fast sicher ist, liegt ein Fehler im Code vor. Wenn Sie eine große negative Zahl haben wollten, warum sollten Sie dann eine große positive Zahl schreiben?
Tags und Links java