Wert von i für (i == -i && i! = 0), um in Java true zurückzugeben

101

Ich habe die folgende ifBedingung.

if (i == -i && i != 0)

Welcher Wert von iwird truefür diese Bedingung in Java zurückgegeben?

Ich kann mir keinen solchen Wert vorstellen, iwenn man die Zweierkomplementnotation in Java berücksichtigt .

Ich hätte auch gerne einen algebraischen Beweis für die Antwort, die diese Bedingung hat (im Zusammenhang mit Java).

Sonnig
quelle
2
wie wäre es wenn (i! = null)
zxc
4
Beachten Sie, dass -0.0auch== 0
Peter Lawrey
2
schreibe es alsif(i && i == -i)
Grijesh Chauhan
10
@GrijeshChauhan In Java? Bist du sicher ?
Denys Séguret
3
@harold Ich habe in den letzten vier Jahren viele Male in Interviews gefragt und nur wenige Leute bekommen es wirklich, auch mit Hinweisen.
Peter Lawrey

Antworten:

126

Der einzige intWert, für den es funktioniert, ist Integer.MIN_VALUE.

Dies liegt daran, dass Ganzzahlen auf die Zweierkomplementierungsmethode negiert werden .

Verwenden von

System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));

Sie sehen, das Integer.MIN_VALUEist

10000000000000000000000000000000

Das Nehmen des negativen Wertes erfolgt durch erstes Tauschen 0und 1, was ergibt

01111111111111111111111111111111

und durch Hinzufügen 1, was gibt

10000000000000000000000000000000

Wie Sie in dem von mir angegebenen Link sehen können, erwähnt Wikipedia das Problem mit den negativsten Zahlen und gibt an, dass es die einzige Ausnahme ist:

Die negativste Zahl im Zweierkomplement wird manchmal als "die seltsame Zahl" bezeichnet, da dies die einzige Ausnahme ist.

Natürlich haben Sie das gleiche Phänomen, Long.Min_Valuewenn Sie es in einer longVariablen speichern .

Beachten Sie, dass dies nur auf Entscheidungen zurückzuführen ist, die hinsichtlich der binären Speicherung von Ints in Java getroffen wurden . Eine andere (schlechte) Lösung könnte zum Beispiel darin bestehen, zu negieren, indem einfach das höchstwertige Bit geändert und die anderen Bits unverändert gelassen werden. Dies hätte dieses Problem mit MIN_VALUE vermieden, aber 2 verschiedene 0Werte und eine komplizierte binäre Arithmetik ergeben (wie hätten Sie das getan? zum Beispiel erhöht?).

Denys Séguret
quelle
2
Es ist erwähnenswert, dass frühe Binärcomputer die Implementierung von Vorzeichen und Größe für Ganzzahlen verwendet haben, die in Ihrem letzten Absatz beschrieben wurden. ebenso wie IEE754-Gleitkommazahlen. en.wikipedia.org/wiki/…
Dan spielt am Feuer
1
Betreff: "Dies bezieht sich nur auf Entscheidungen, die in Bezug auf die binäre Speicherung von Ints getroffen wurden": Und die Entscheidungen, wie mit Überlauf umgegangen werden soll. Die von Java verwendete Regel ist nicht dieselbe wie die von (sagen wir) C verwendete Regel oder die von (sagen wir) Standard ML verwendete Regel, obwohl alle diese auf einer Vielzahl von Systemen ausgeführt werden.
Ruakh
2
Erwähnenswert ist, dass es in der Java- Spezifikation dokumentiert ist : "Die Java-Programmiersprache verwendet die Zweierkomplementdarstellung für Ganzzahlen, und der Bereich der Zweierkomplementwerte ist nicht symmetrisch, sodass die Negation des maximalen negativen int oder long zu demselben Maximum führt negative Zahl."
Chesterbr
25

Der Wert, den Sie suchen, ist Integer.MIN_VALUE.


Ich hätte auch gerne einen algebraischen Beweis für die Antwort, die diese Bedingung hat (im Zusammenhang mit Java).

Das ist für Stack Exchange kein Thema. Sie können dies jedoch ausgehend von der Definition von Java-Ganzzahlen ( JLS 4.2 ) tun.

"Die Integraltypen sind Byte, Short, Int und Long, deren Werte 8-Bit-, 16-Bit-, 32-Bit- und 64-Bit-Ganzzahlen mit Zweierkomplement sind ..."

und

"Die Werte der Integraltypen sind ganze Zahlen in den folgenden Bereichen ... Für int von -2147483648 bis einschließlich 2147483647"

und die Definition des unären Java-Operators '-' ( JLS 15.15.4 ):

"Bei ganzzahligen Werten entspricht die Negation der Subtraktion von Null. Die Java-Programmiersprache verwendet die Zweierkomplementdarstellung für Ganzzahlen, und der Bereich der Zweierkomplementwerte ist nicht symmetrisch, sodass die Negation des maximalen negativen int oder long dazu führt gleiche maximale negative Zahl. In diesem Fall tritt ein Überlauf auf, es wird jedoch keine Ausnahme ausgelöst. Für alle ganzzahligen Werte x ist -x gleich (~ x) +1. "

Stephen C.
quelle
3
Long.MIN_VALUE auch.
Juvanis
1
Welches ist 100000 .., und wenn ich 2 Kompliment davon bekomme, ist es wieder 011111 ... + 1 = 100000 ... aber Sie wissen es oben auf Ihrem Kopf oder wir können jede Logik anwenden?
Sunny
1
Wie ich gelesen habe ... Java Int Arithmetik ist Arithmetik Mod 2power32, also dachte ich, ob wir diesen Wert in nur 1 oder 2 Zeilen beweisen können ... wenn es ein großer Beweis ist ... dann kein Problem.
Sunny
2
@ Sunny es kann nicht zu schwer sein zu beweisen. Im ganzzahligen Bereich haben alle positiven Zahlen ein negatives Gegenstück (so i != -i). Damit bleiben zwei Zahlen im Bereich: 0und Integer.MIN_VALUE. Wegen i != 0in deinem Wenn ist nur MIN_VALUEnoch übrig.
Vincent van der Weele
1
@ Heuster - diese Argumentation funktioniert ... aber es hängt von ein oder zwei Annahmen ab, die einen Beweis erfordern.
Stephen C
18

Zusätzlich zu den bisher gegebenen Antworten ...

Insgesamt gibt es vier Werte

int i = Integer.MIN_VALUE;
long i = Long.MIN_VALUE;
Integer i = Integer.valueOf(Integer.MIN_VALUE);
Long i = Long.valueOf(Long.MIN_VALUE);

Die umschlossenen Werte werden entpackt, sodass sie auch für diesen Ausdruck gelten.

Hinweis: Math.abs-Dokumente.

public static int abs (int a)

Gibt den absoluten Wert eines int-Werts zurück. Wenn das Argument nicht negativ ist, wird das Argument zurückgegeben. Wenn das Argument negativ ist, wird die Negation des Arguments zurückgegeben.

Beachten Sie, dass wenn das Argument dem Wert von Integer.MIN_VALUE entspricht, dem negativsten darstellbaren int-Wert, das Ergebnis derselbe Wert ist, der negativ ist.

und

öffentliche statische lange abs (lange a)

Gibt den absoluten Wert eines langen Wertes zurück. Wenn das Argument nicht negativ ist, wird das Argument zurückgegeben. Wenn das Argument negativ ist, wird die Negation des Arguments zurückgegeben.

Beachten Sie, dass wenn das Argument dem Wert von Long.MIN_VALUE entspricht, dem negativsten darstellbaren Long-Wert, das Ergebnis derselbe Wert ist, der negativ ist.

Es ist überraschend, dass Math.abs möglicherweise eine negative Zahl zurückgibt. Dies geschieht entweder, weil a) in diesen Fällen keine positiven Werte für -MIN_VALUE vorliegen b) die -Berechnung zu einem Überlauf führt.

Interessant ist auch, warum Byte.MIN_VALUE, Short.MIN_VALUE dies nicht tun. Dies liegt daran -, dass der Typ intfür diese geändert wird und somit kein Überlauf erfolgt.

Character.MIN_VALUE hat kein Problem, da es 0 ist.

Float.MIN_VALUE und Double.MIN_VALUE haben eine andere Bedeutung. Dies sind die kleinsten darstellbaren Werte größer als Null. Sie haben also gültige negative Werte, die nicht sie selbst sind.

Peter Lawrey
quelle
1
Ich habe mich über Byte.MIN_VALUE und andere Möglichkeiten gewundert, Ihre Antwort hat dies vorausgesetzt. Danke
Cengiz Can
14

Wie die anderen erwähnt haben, wird dies nur von erfüllt Integer.MIN_VALUE. Lassen Sie mich zum Beweis eine leicht verständliche Erklärung anbieten, die nicht binär ist (obwohl sie immer noch darin verwurzelt ist).

Beachten Sie, dass Integer.MIN_VALUEgleich -2^31oder -2147483648und Integer.MAX_VALUEgleich 2^31-1oder ist 2147483647. -Integer.MIN_VALUEist 2^31, was jetzt zu groß für eine Ganzzahl ist (da es vorbei ist MAX_VALUE), wodurch ein Ganzzahlüberlauf verursacht wird, der es Integer.MIN_VALUEerneut macht. Dies MIN_VALUEist die einzige Ganzzahl, die dies tut, da sie neben 0 die einzige Zahl ohne negatives Äquivalent ist.

Mark M.
quelle
2
@dystroy Eigentlich habe ich nach einer Erklärung gesucht, laut Mark gibt es keine Nummer wie +2147483648 im int-Bereich, also sollte der erste Verdächtige diese Nummer anders als 0 sein. Der Bereich ist -2 ^ n bis 2 ^ n-1. Es gibt also kein positives Gegenstück zu -2 ^ n. Dies ist nur ein weiterer möglicher int-Wert.
Sunny
1
Ich habe es nicht binär erklärt, da es bereits von jemand anderem behandelt wurde (im Grunde ist int ein 32-Bit-Wert, deshalb hat es diese Grenzen). Negativ oder Negativ ist auch positiv, sodass die Bedingungen weiterhin gelten können.
Mark M
1
Seltsamerweise kann die Zahl in Java 2147483648nur unter einem Umstand im Quellcode erscheinen: als Operand des unären Minusoperators (JLS 3.10.1).
Eric Jablow
6

Vorläufiger algebraischer Beweis unter Verwendung von modulo 2^32Arithmetik:

i == -ikann umgeschrieben werden als 2 * i == 0( ibeidseitig hinzufügen ) oder i << 1 == 0.

Diese Gleichung hat zwei Lösungen der Form i == 0 >> 1, nämlich 0bund 10000000000000000000000000000000berhalten durch Verschieben entweder 0oder 1links.

Wird die Lösung i == 0ausgeschlossen, bleibt die Lösung erhalten i == 100000000000000000000000000000000b.

Yves Daoust
quelle
0

Vielleicht ist es nicht zu lehrreich, aber anstatt zu denken, Sie könnten diesen Code ausführen:

    for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
    {
        if (i == -i && i != 0)
        {
            System.out.println(i);
        }
    }

um zu sehen, dass es druckt

-2147483648
-2147483648

unendlich :)

Kuba
quelle
Wie denkst du, ist es unendlich?
JBelter
Weil i <= Integer.MAX_VALUE niemals falsch sein wird
Kuba
1
Ahh sehr wahr, dachte ich sah streng<
JBelter