Frage

Warum ist dieser Java -Code

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

Beim Ausgang, Ausgabe

1
1
107374182400
0

statt der erwarteten

1
1
107374182400
107374182400

Ausgang?

War es hilfreich?

Lösung 2

107374182400 ist genau das 25 -fache des gesamten Bereichs einer Ganzzahl (2^32), was bedeutet, dass, wenn Sie versuchen, es in eine Ganzzahl zu passen Überlauf. Und weil es genau das 25 -mal passen würde, endet es genau auf 0 (dies ist ein Zufall und andere riesige Multiplikationen können entweder positiv oder negativ enden). Und Sie verwenden eine Ganzzahl bis zu dem Punkt, an dem Sie lange gegossen haben

long a1 = 100 * 1024 * 1024 * 1024;

ist äquivalent zu

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

Wenn Sie einen einzigen Long in den Ausdruck einfügen, ist es gezwungen, lange Mathematik nicht ganzzahlige Mathematik zu verwenden, was das Problem beseitigt

Andere Tipps

 long a2 = 100L * 1024 * 1024 * 1024;

In diesem Vorgang ist jedoch mindestens ein Operand long. Daher wird der Betrieb mit 64-Bit-Präzision durchgeführt, und das Ergebnis des numerischen Operators ist vom Typ long. Der andere nicht lange Operand wird auf Typ erweitert long durch Numerische Werbung und führte den Wert, der auf Variable gespeichert wird a2.

 long a1 = 100 * 1024 * 1024 * 1024;

Der konstante Expression der einfachen Ganzzahl wurde das Ergebnis des Ausdrucks als Typ berechnet int. Der berechnete Wert jedoch zu groß, um in eine Ganzzahl zu passen, und daher überflutet, was dazu führt, dass 0 und wird auf gespeichert a1 Variable.

Bearbeiten: Wie im folgenden Kommentar gefragt:

Warum wird es nicht negativ?

Weil während Ganzzahlberechnung Die zweite Berechnung entspricht zu 25 * 2^32 wo ^ hat die Machtbedeutung und 2^32 ganzzahliger Wert ist 0. Aber zu erklären, warum der Wert ist 0: In binär:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31 ist eine negative Ganzzahl (-2147483648) Wie das Zeichenbit ist 1 Und daher 2 ^ 32 ist nur eine Multiplikation von 2 zu 2 ^ 31: Eine linke Verschiebung und das Zeichenbit wird werden 0 und daher ist das Ergebnis 0.

Probier das aus java language specification: 4.2.2: Integer operation für Details.

Es könnte sein, dass der Ausdruck auf dem Recht von a1 wird zuerst als als berechnet int und später konvertiert zu long. Wenn es gleich ist 0 als an int Es wird bleiben 0 Als ein long

Gemäß Dokumentation von lexikalischen Literalen Es wird erwähnt, dass,

Die Art eines wörtlichen Wörtels wird wie folgt bestimmt:
- Die Art eines Ganzzahl wörtlichen (§3.10.1), der mit L oder L endet, ist lang (§4.2.1).
- Die Art eines anderen ganzzahligen Literales ist int (§4.2.1).

So dein Ausdruck, 100 * 1024 * 1024 * 1024 wird bewertet als int primitiver Datentyp, weil l oder L wird in keinem numerischen Wert erwähnt. und das Ergebnis ist 107374182400 dh in binär ist es 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 und int ist 32-Bit so niedrig, dass 32-Bit wie in erwähnt genommen werden Beispiel 4.2.2-1. Ganzzahloperationen welche entsteht zu 0

Es wird auch in derselben Dokumentation erwähnt, dass,

Wenn ein ganzzahliger Operator außer einem Schaltoperator mindestens einen Typenbetrieb vom Typ lang hat, wird der Betrieb mit einer 64-Bit-Präzision durchgeführt, und das Ergebnis des numerischen Bedieners ist vom Typ lang. Wenn der andere Operand nicht lange ist, wird es zuerst erweitert (§5.1.5), um lange nach numerische Werbung zu tippen

Es bedeutet, dass jeder Wert im Ausdruck enthält l oder L dann alle int Die Werte werden auf 64 Bit erweitert.

BEARBEITEN Im der Kommentar es wird auch gefragt

Warum wird es nicht negativ?

Ich denke es auch beantwortet die obige Frage

long a4 = 1L; // kein Problem dabei

long a3 = 1; // Hier wird links als Ganzzahl angesehen und zum Zeitpunkt der Zuordnung wird es bis zu lang gegossen, sodass das Ergebnis wie erwartet erneut Ergebnis ist

long a2 = 100L * 1024 * 1024 * 1024; (Hier haben Sie 100L verwendet, damit andere bis zu lange so erwartet werden, dass die Ausgabe erwartet wird)

long a1 = 100 * 1024 * 1024 * 1024; (Da eine primitive Ziffer in Java standardmäßig als INT betrachtet wird, wird dies als Ganzzahlmultiplikation betrachtet, sodass es außer Reichweite ist und in 0 führt.)

Hier ist, was Sie getan haben: Sie haben zugewiesen 100 * 1024 * 1024 * 1024zu einem langen Datentyp, aber Sie haben das nicht gesagt 100 * 1024 * 1024 * 1024 ist ein langer Wert

Standardmäßig ist Java Compiler der Meinung, dass es sich um eine Ganzzahl handelt. Da Integer nicht so viel Wert haben kann, wird dies ein falsches Ergebnis zeigen. Ich hoffe es hilft !

Grund ist Ganzzahlüberlauf
als Ausgabe von 100 * 1024 * 1024 * 1024; ist eine Ganzzahl (int) nicht long

und in long a2 = 100L * 1024 * 1024 * 1024; Sie geben an, dass einer der Wert ist long (hier 100L) und die Multiplikation mit diesem Wert führt dazu long Wert, der korrekt gespeichert wird in a2

Wenn Sie in Java int * int haben, berechnet es die Ausgabe als int. Es gibt das Ergebnis nur so lange, wenn Sie int * lang sind. In Ihrem Fall hat der 100 * 1024 * 1024 * 1024 ein Ergebnis, das int überläuft.

Durch das Hinzufügen eines "L" wird der Operand also langwierig sein, und die Berechnung speichert die Werte lang. Und natürlich tritt kein Überlauf auf und ein korrektes Ergebnis kann ausgegeben werden (dh A2).

Nummer 3 hat funktioniert, da Sie einen langen Typ angegeben haben, der 100 l ist. Deshalb ist es eine lange Multiplikation und könnte gespeichert werden. Andererseits ist Nummer 4 eine Ganzzahl-Multiplikation mit dem Max-Wert 2^32-1, deshalb haben Sie einen Überlauf und der Null-Standardwert erschien.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top