Dieser Code:
System.out.println(Math.abs(Integer.MIN_VALUE));
Kehrt zurück -2147483648
Sollte es nicht den absoluten Wert als zurückgeben 2147483648
?
java
absolute-value
user665319
quelle
quelle
Das Verhalten, auf das Sie hinweisen, ist in der Tat kontraintuitiv. Dieses Verhalten ist jedoch das vom Javadoc angegebene für
Math.abs(int)
:Das heißt,
Math.abs(int)
sollte sich wie der folgende Java-Code verhalten:Das heißt, im negativen Fall
-x
.Gemäß dem JLS-Abschnitt 15.15.4 ist das
-x
gleich(~x)+1
, wobei~
der bitweise Komplementoperator ist.Um zu überprüfen, ob dies richtig klingt, nehmen wir als Beispiel -1.
Der ganzzahlige Wert
-1
kann0xFFFFFFFF
in Java wie hexadezimal angegeben werden (überprüfen Sie dies mit einerprintln
oder einer anderen Methode). Nehmen-(-1)
gibt also:Also funktioniert es.
Versuchen wir es jetzt mit
Integer.MIN_VALUE
. In dem Wissen, dass die niedrigste Ganzzahl durch0x80000000
das erste auf 1 gesetzte Bit und die 31 verbleibenden auf 0 gesetzten Bits dargestellt werden kann, haben wir:Und deshalb
Math.abs(Integer.MIN_VALUE)
kehrt zurückInteger.MIN_VALUE
. Beachten Sie auch , dass0x7FFFFFFF
istInteger.MAX_VALUE
.Wie können wir jedoch in Zukunft Probleme aufgrund dieses kontraintuitiven Rückgabewerts vermeiden?
Wir könnten, wie von @Bombe betont , unsere
int
slong
vorher besetzen . Wir müssen jedoch auchint
s, was da nicht funktioniertInteger.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE)
.long
s fort und hoffen Sie irgendwie, dass wir niemalsMath.abs(long)
mit einem Wert gleich anrufenLong.MIN_VALUE
, da wir auch habenMath.abs(Long.MIN_VALUE) == Long.MIN_VALUE
.Wir können
BigInteger
s überall verwenden, weilBigInteger.abs()
es in der Tat immer einen positiven Wert zurückgibt. Dies ist eine gute Alternative, wenn auch etwas langsamer als das Bearbeiten von rohen Ganzzahltypen.Wir können unseren eigenen Wrapper für Folgendes schreiben
Math.abs(int)
:int positive = value & Integer.MAX_VALUE
(im Wesentlichen überlaufend vonInteger.MAX_VALUE
nach0
statt stattInteger.MIN_VALUE
)Abschließend scheint dieses Problem seit einiger Zeit bekannt zu sein. Siehe zum Beispiel diesen Eintrag über die entsprechende Findbugs-Regel .
quelle
Folgendes sagt das Java-Dokument für Math.abs () in javadoc :
quelle
Um das erwartete Ergebnis zu sehen, gehen Sie wie folgt
Integer.MIN_VALUE
vorlong
:quelle
Math.abs
es nichtMath.abs(Long.MIN_VALUE) == Long.MIN_VALUE
ArithmeticException
? Das Verhalten ist auch in der API-Dokumentation klar dokumentiert.Math.abs(long)
. Ich entschuldige mich für meinen Fehler hier: Ich habe gedacht, dass Sie die VerwendungMath.abs(long)
als Fix vorgeschlagen haben, als Sie es als einfache Möglichkeit gezeigt haben, "das Ergebnis zu sehen, das der Fragesteller erwartet". Es tut uns leid.2147483648 kann in Java nicht in einer Ganzzahl gespeichert werden, seine binäre Darstellung entspricht der von -2147483648.
quelle
Es
(int) 2147483648L == -2147483648
gibt jedoch eine negative Zahl, die kein positives Äquivalent hat, sodass es keinen positiven Wert dafür gibt. Sie werden das gleiche Verhalten mit Long.MAX_VALUE sehen.quelle
Es gibt eine Lösung dafür in Java 15 wird eine Methode zu int und long sein. Sie werden in den Klassen anwesend sein
Die Methoden.
Wenn Sie bestehen
ODER
Eine Ausnahme wird ausgelöst.
https://bugs.openjdk.java.net/browse/JDK-8241805
Ich würde gerne sehen, ob entweder Long.MIN_VALUE oder Integer.MIN_VALUE übergeben wird. Ein positiver Wert wäre return und keine Ausnahme, aber.
quelle
Math.abs funktioniert nicht immer mit großen Zahlen. Ich verwende diese kleine Codelogik, die ich mit 7 Jahren gelernt habe!
quelle
s
hierNum
equalsInteger.MIN_VALUE
vor dem Snippet?