Lesen Sie dies in Effektivem Java von Joshua Bloch.
Ich habe die Antwort für diese Frage gefunden und hier ist die Erklärung:
Computer arbeiten mit binärem aritmenticic, die Logik von Math.abs
in Java oder die Funktion absolute
in jeder Sprache ist wie folgt:
Hinweis: So finden Sie das Kompliment von 2
Bei einer bestimmten Zahl finden wir zuerst das Kompliment 1 und fügen dann 1 hinzu. Für z.B.
Betrachte unsere Nummer als 10101
1 Kompliment = 01010
2er Kompliment = 01011
(addiert 1 zum Kompliment 1)
Nun, um es einfach und klar zu machen, lassen Sie uns sagen, dass unsere Integer (signed) Größe 3 Bit ist, dann ist hier die mögliche Liste von Zahlen, die mit den vier Bits erzeugt werden können:
%Vor% Nun, da dies vorzeichenbehaftet ist, bedeutet dies, dass die Hälfte der Zahlen negativ und die andere Hälfte positiv ist (die negativen Zahlen sind diejenigen mit dem ersten Bit 1). Lassen Sie uns von 000
beginnen und versuchen Sie, seine negative Zahl zu finden, es wäre das Kompliment der beiden von 000
.
Aus der obigen Demonstration finden wir das 2er-Kompliment von 111(-1) is 001(1)
, ähnlich das 2er-Komplement von 110(-2) is 010(2)
, das 2er-Kompliment von 101(-3) is 011(3)
und das 2er-Kompliment von 100(-4) is 100(-4)
, und wir können sehen, dass -4 am kleinsten ist negative Zahl möglich mit 3 Bits.
Dies ist der Grund, warum absolute von Integer.MIN_VALUE
ist Integer.MIN_VALUE
.
In Java, wenn ich %code% sage. Ich bekomme den gleichen Wert wie die Antwort, was bedeutet, dass %code% %code% enthält. Das habe ich auch in C ++ verifiziert.
Warum dieses Verhalten?
Lesen Sie dies in Effektivem Java von Joshua Bloch.
Ich habe die Antwort für diese Frage gefunden und hier ist die Erklärung: Computer arbeiten mit binärem aritmenticic, die Logik von %code% in Java oder die Funktion %code% in jeder Sprache ist wie folgt:
%Vor%Hinweis: So finden Sie das Kompliment von 2
Bei einer bestimmten Zahl finden wir zuerst das Kompliment 1 und fügen dann 1 hinzu. Für z.B. Betrachte unsere Nummer als %code% 1 Kompliment = %code% 2er Kompliment = %code% (addiert 1 zum Kompliment 1)
Nun, um es einfach und klar zu machen, lassen Sie uns sagen, dass unsere Integer (signed) Größe 3 Bit ist, dann ist hier die mögliche Liste von Zahlen, die mit den vier Bits erzeugt werden können:
%Vor%Nun, da dies vorzeichenbehaftet ist, bedeutet dies, dass die Hälfte der Zahlen negativ und die andere Hälfte positiv ist (die negativen Zahlen sind diejenigen mit dem ersten Bit 1). Lassen Sie uns von %code% beginnen und versuchen Sie, seine negative Zahl zu finden, es wäre das Kompliment der beiden von %code% .
%Vor%Aus der obigen Demonstration finden wir das 2er-Kompliment von %code% , ähnlich das 2er-Komplement von %code% , das 2er-Kompliment von %code% und das 2er-Kompliment von %code% , und wir können sehen, dass -4 am kleinsten ist negative Zahl möglich mit 3 Bits.
Dies ist der Grund, warum absolute von %code% ist %code% .
Es gibt eine inhärente Asymmetrie, die die Ursache für diesen Effekt ist. Die Anzahl der 32-Bit-Bitmuster ist gerade. Eines dieser Muster wird für Null verwendet. Das hinterlässt eine ungerade Anzahl von Nicht-Null-Werten. Die Anzahl der positiven Werte und die Anzahl der negativen Werte können nicht gleich sein, da ihre Summe ungerade ist.
In der Zweierkomplementdarstellung, die für Ganzzahlen von Java verwendet wird, ist die Anzahl der negativen Zahlen um eins größer als die Anzahl der positiven Zahlen. Jede negative Zahl außer Integer.MIN_VALUE entspricht einer positiven Zahl, die sowohl ihre Negation als auch ihren absoluten Wert darstellt. Integer.MIN_VALUE ist übrig, ohne entsprechenden positiven int. Math.abs und die Negation ordnen es sich selbst zu.
Math.abs (int) docs sagt Wenn das Argument negativ ist, wird die Negation des Arguments zurückgegeben. JLS 15.15.4. Unärer Minusoperator sagt Für alle ganzzahligen Werte x ist -x gleich (~ x) +1 .
-Integer.MIN_VALUE = ~ Integer.MIN_VALUE + 1 = ~ 0x80000000 + 1 = 0x7FFFFFFF + 1 = 0x80000000 = Integer.MIN_VALUE
Sie könnten erwarten, dass der absolute Wert von %code% %code% ist, aber dieser Wert liegt außerhalb der primitiven %code% size. Und %code% ist wieder %code% . Das ist alles.
Dies liegt an der Art, wie Zweierkomplement-Zahlensysteme funktionieren. %code% entspricht 0x80000000. Der Standardweg, um es zu negieren, ist, sein Einerkomplement zu nehmen (0x7FFFFFFF in diesem Fall) und 1 hinzuzufügen, und in diesem Fall würde es wieder auf 0x80000000 überlaufen.
Warum dieses Verhalten?
Es ist eine mathematische Konsequenz der Wahl der Darstellung, die in allen modernen Computern verwendet wird.
Hier ist ein informeller Beweis dafür, warum es so ist.
Eine vorzeichenbehaftete Binärzahldarstellung mit N Bits hat 2
Entferne Null von der Menge. Die Menge hat jetzt eine ungerade Anzahl von Elementen.
Entfernen Sie nun alle Paare von Zahlen der Form %code% . Jedes Mal, wenn wir ein Zahlenpaar entfernen, enthält die Menge still eine ungerade Anzahl von Elementen.
Uns bleibt jetzt eine Menge, die eine ungerade Anzahl von ganzen Zahlen enthält, für die %code% in der Menge ist, aber %code% ist nicht in der Menge. Da die eingestellte Größe ungerade ist, kann sie nicht leer sein. d. h. es gibt mindestens eine Nummer mit dieser Eigenschaft.
In den Darstellungen, die von Java spezifiziert werden (und tatsächlich alle anderen praktischen Sprachen verwenden), haben Integertypen 2 N-1
Genau genommen muss eine Ganzzahldarstellung diese Anomalie nicht haben:
Es ist möglich, zwei Nullen (-0 und +0) zu haben; z.B. signierte Magnitude oder eigene Ergänzung Darstellungen. (Dies macht Schritt 2 des Beweises ungültig: Es gibt jetzt 2 Nullen zum Entfernen.)
Es ist möglich, -2 N-1 auszunehmen; d. h. es zu einem illegalen Wert machen. (Dies macht Schritt 1 des Beweises ungültig: Der Anfangssatz hat jetzt eine ungerade Anzahl von Werten.)
Es ist möglich, Ganzzahlarithmetik anzugeben, so dass (zum Beispiel) das Negieren von MIN_VALUE eine Ausnahme auslöst. Zum Beispiel würde %code% eine Ausnahme auslösen.
All diese Dinge haben jedoch erhebliche Auswirkungen auf die Leistung, zumal moderne Computerhardware nativ nur Zweierkomplementarithmetik unterstützt. Sie haben auch Probleme beim Schreiben von zuverlässigen Integer-Codes ...
Math.abs (int) docs sagt Wenn das Argument negativ ist, wird die Negation des Arguments zurückgegeben. JLS 15.15.4. Unärer Minusoperator sagt Für alle ganzzahligen Werte x ist -x gleich (~ x) +1 .
-Integer.MIN_VALUE = ~ Integer.MIN_VALUE + 1 = ~ 0x80000000 + 1 = 0x7FFFFFFF + 1 = 0x80000000 = Integer.MIN_VALUE
Warum dieses Verhalten?
Es ist eine mathematische Konsequenz der Wahl der Darstellung, die in allen modernen Computern verwendet wird.
Hier ist ein informeller Beweis dafür, warum es so ist.
Eine vorzeichenbehaftete Binärzahldarstellung mit N Bits hat 2
Entferne Null von der Menge. Die Menge hat jetzt eine ungerade Anzahl von Elementen.
Entfernen Sie nun alle Paare von Zahlen der Form {n, -n}
. Jedes Mal, wenn wir ein Zahlenpaar entfernen, enthält die Menge still eine ungerade Anzahl von Elementen.
Uns bleibt jetzt eine Menge, die eine ungerade Anzahl von ganzen Zahlen enthält, für die n
in der Menge ist, aber -n
ist nicht in der Menge. Da die eingestellte Größe ungerade ist, kann sie nicht leer sein. d. h. es gibt mindestens eine Nummer mit dieser Eigenschaft.
In den Darstellungen, die von Java spezifiziert werden (und tatsächlich alle anderen praktischen Sprachen verwenden), haben Integertypen 2 N-1 MIN_VALUE
. Diese Darstellung nennt sich Zweierkomplement .
Genau genommen muss eine Ganzzahldarstellung diese Anomalie nicht haben:
Es ist möglich, zwei Nullen (-0 und +0) zu haben; z.B. signierte Magnitude oder eigene Ergänzung Darstellungen. (Dies macht Schritt 2 des Beweises ungültig: Es gibt jetzt 2 Nullen zum Entfernen.)
Es ist möglich, -2 N-1 auszunehmen; d. h. es zu einem illegalen Wert machen. (Dies macht Schritt 1 des Beweises ungültig: Der Anfangssatz hat jetzt eine ungerade Anzahl von Werten.)
Es ist möglich, Ganzzahlarithmetik anzugeben, so dass (zum Beispiel) das Negieren von MIN_VALUE eine Ausnahme auslöst. Zum Beispiel würde Math.abs(Integer.MIN_VALUE)
eine Ausnahme auslösen.
All diese Dinge haben jedoch erhebliche Auswirkungen auf die Leistung, zumal moderne Computerhardware nativ nur Zweierkomplementarithmetik unterstützt. Sie haben auch Probleme beim Schreiben von zuverlässigen Integer-Codes ...
Dies liegt an der Art, wie Zweierkomplement-Zahlensysteme funktionieren. Integer.MIN_VALUE
entspricht 0x80000000. Der Standardweg, um es zu negieren, ist, sein Einerkomplement zu nehmen (0x7FFFFFFF in diesem Fall) und 1 hinzuzufügen, und in diesem Fall würde es wieder auf 0x80000000 überlaufen.