Valore di i per (i == -i && i! = 0) per restituire true in Java


101

Ho la seguente ifcondizione.

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

Quale valore irestituirà trueper questa condizione in Java?

Non riesco a pensare a un tale valore di iconsiderare la notazione in complemento a due in Java.

Mi piacerebbe anche avere una prova algebrica di qualunque risposta abbia questa condizione (nel contesto di Java)?


2
che ne dici di if (i! = null)
zxc

4
Si noti che -0.0è anche== 0
Peter Lawrey,

2
scrivilo comeif(i && i == -i)
Grijesh Chauhan

10
@GrijeshChauhan In Java? Sei sicuro ?
Denys Séguret

3
@harold Ho chiesto molte volte nelle interviste negli ultimi quattro anni e poche persone lo capiscono davvero anche con suggerimenti.
Peter Lawrey

Risposte:


126

L'unico intvalore per cui funziona è Integer.MIN_VALUE.

È perché gli interi vengono negati usando il modo del complemento a due .

utilizzando

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

vedi che Integer.MIN_VALUEè

10000000000000000000000000000000

Per prendere il valore negativo si scambia prima 0e 1, che dà

01111111111111111111111111111111

e aggiungendo 1, che dà

10000000000000000000000000000000

Come puoi vedere nel link che ho fornito, Wikipedia menziona il problema con i numeri più negativi e specifica che è l'unica eccezione:

Il numero più negativo in complemento a due è talvolta chiamato "il numero strano", perché è l'unica eccezione.

Ovviamente hai lo stesso fenomeno Long.Min_Valuese lo memorizzi in una longvariabile.

Si noti che ciò è dovuto solo alle scelte che sono state fatte per quanto riguarda l'archiviazione binaria di int in Java . Un'altra (cattiva) soluzione potrebbe ad esempio essere stata quella di negare semplicemente cambiando il bit più significativo e lasciando invariati gli altri bit, questo avrebbe evitato questo problema con MIN_VALUE ma avrebbe reso 2 0valori diversi e complicata aritmetica binaria (come avresti incrementato per esempio?).


2
Vale la pena notare che i primi computer binari usavano l'implementazione del segno e della grandezza per gli interi descritta nel tuo ultimo paragrafo; così come i numeri in virgola mobile IEE754. en.wikipedia.org/wiki/…
Dan sta armeggiando con Firelight

1
Re: "questo è solo correlato alle scelte che sono state fatte riguardo alla memorizzazione binaria di int": e le scelte su come gestire l'overflow. La regola che utilizza Java non è la stessa della regola usata da (diciamo) C o della regola usata da (diciamo) Standard ML, anche se tutti questi funzionano su un'ampia varietà di sistemi.
ruakh

2
Vale la pena ricordare che è documentato nelle specifiche Java : "Il linguaggio di programmazione Java utilizza la rappresentazione in complemento a due per i numeri interi e l'intervallo dei valori in complemento a due non è simmetrico, quindi la negazione del massimo negativo int o long risulta nello stesso massimo numero negativo."
chesterbr

25

Il valore che stai cercando è Integer.MIN_VALUE.


Mi piacerebbe anche avere una prova algebrica di qualunque risposta abbia questa condizione (nel contesto di java)?

Questo è fuori tema per Stack Exchange. Ma potresti farlo partendo dalla definizione di interi Java ( JLS 4.2 )

"I tipi integrali sono byte, short, int e long, i cui valori sono interi a complemento di due con segno a 8 bit, 16 bit, 32 bit e 64 bit ..."

e

"I valori dei tipi integrali sono numeri interi nei seguenti intervalli ... Per int, da -2147483648 a 2147483647, inclusi"

e la definizione dell'operatore unario '-' Java ( JLS 15.15.4 ):

"Per i valori interi, la negazione è la stessa della sottrazione da zero. Il linguaggio di programmazione Java utilizza la rappresentazione in complemento a due per i numeri interi e l'intervallo dei valori in complemento a due non è simmetrico, quindi la negazione del massimo negativo int o long risulta in tale stesso numero massimo negativo. In questo caso si verifica un overflow, ma non viene generata alcuna eccezione. Per tutti i valori interi x, -x è uguale a (~ x) +1. "


3
Long.MIN_VALUE pure.
Juvanis

1
che è 100000 .., e se ricevo i complimenti di 2, è di nuovo 011111 ... + 1 = 100000 ... ma lo sai in cima alla tua testa o possiamo applicare una logica?
Soleggiato

1
Come ho letto .. l'aritmetica int di java è aritmetica mod 2power32, quindi stavo pensando se possiamo provare questo valore in solo 1 o 2 righe .. se è una grande prova .. allora nessun problema.
Soleggiato

2
@Sunny non può essere troppo difficile da dimostrare. Nell'intervallo intero, tutti i numeri positivi hanno una controparte negativa (quindi i != -i). Restano due numeri nell'intervallo: 0e Integer.MIN_VALUE. A causa del i != 0tuo se, MIN_VALUErimane solo .
Vincent van der Weele

1
@Heuster - quel ragionamento funziona ... ma dipende da uno o due presupposti che richiedono una prova.
Stephen C

18

Oltre alle risposte fornite finora ...

Ci sono quattro valori in totale

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

I valori inseriti nel wrapper vengono scartati, quindi sono validi anche per questa espressione.

Nota: documenti Math.abs.

pubblico statico int abs (int a)

Restituisce il valore assoluto di un valore int. Se l'argomento non è negativo, viene restituito l'argomento. Se l'argomento è negativo, viene restituita la negazione dell'argomento.

Si noti che se l'argomento è uguale al valore di Integer.MIN_VALUE, il valore int rappresentabile più negativo, il risultato è lo stesso valore, che è negativo.

e

pubblico statico lungo addominali (lungo a)

Restituisce il valore assoluto di un valore lungo. Se l'argomento non è negativo, viene restituito l'argomento. Se l'argomento è negativo, viene restituita la negazione dell'argomento.

Si noti che se l'argomento è uguale al valore di Long.MIN_VALUE, il valore lungo rappresentabile più negativo, il risultato è lo stesso valore, che è negativo.

È sorprendente che Math.abs possa restituire un numero negativo. Ciò accade perché a) non ci sono valori positivi per -MIN_VALUE in questi casi b) eseguendo il- calcolo risulta in un overflow.

Ciò che è interessante è anche perché Byte.MIN_VALUE, Short.MIN_VALUE non lo fanno. Questo perché -il tipo cambia inint per questi e quindi nessun overflow.

Character.MIN_VALUE non ha problemi perché è 0.

Float.MIN_VALUE e Double.MIN_VALUE hanno un significato diverso. Questi sono il valore rappresentabile più piccolo maggiore di zero. Quindi hanno valori negativi validi che non sono loro stessi.


1
Mi chiedevo Byte.MIN_VALUE e altre possibilità, la tua risposta lo ha fornito. Grazie
Cengiz Can

14

Come gli altri hanno già detto, questo è soddisfatto solo da Integer.MIN_VALUE. Per quanto riguarda la prova, permettetemi di offrire una spiegazione più facile da capire diversa da quella binaria (sebbene sia ancora radicata in questo).

Si noti che Integer.MIN_VALUEè uguale a -2^31o -2147483648ed Integer.MAX_VALUEè uguale a 2^31-1o 2147483647. -Integer.MIN_VALUEè 2^31, che ora è troppo grande per un numero intero (poiché è passato MAX_VALUE) causando così un overflow di numero intero, rendendolo di Integer.MIN_VALUEnuovo. È l'unico numero intero che lo fa poiché MIN_VALUEè l'unico numero senza equivalente negativo a parte 0.


2
@dystroy in realtà stavo cercando una spiegazione, secondo Mark, non esiste un numero come +2147483648 nell'intervallo int, quindi il primo sospetto dovrebbe essere questo numero diverso da 0. L'intervallo è da -2 ^ n a 2 ^ n-1. Quindi non esiste una controparte positiva per -2 ^ n. Questo è solo un altro possibile valore int.
Soleggiato

1
Non ho spiegato in binario poiché era già coperto da qualcun altro (fondamentalmente int è un valore a 32 bit, ecco perché ha quei limiti). Inoltre, negativo o negativo è positivo, quindi i termini possono ancora essere applicati.
Mark M

1
Stranamente in Java, il numero 2147483648può apparire nel codice sorgente solo in una circostanza: come operando dell'operatore meno unario (JLS 3.10.1).
Eric Jablow

6

Prova algebrica provvisoria, usando l' modulo 2^32aritmetica:

i == -ipuò essere riscritto come 2 * i == 0(aggiungendo isu entrambi i lati), oi << 1 == 0 .

Questa equazione ha due soluzioni della forma i == 0 >> 1, vale a dire 0be 10000000000000000000000000000000bottenuta spostando in uno 0o l'altro1 a sinistra.

Escludendo la soluzione i == 0, resta la soluzione i == 100000000000000000000000000000000b.


0

Forse non è troppo istruttivo, ma invece di pensare che potresti eseguire questo codice:

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

per vedere che stampa

-2147483648
-2147483648

infinitamente :)


Come pensi che sia infinitamente?
JBelter

Perché i <= Integer.MAX_VALUE non sarà mai falso
Kuba

1
Ahh molto vero, pensavo di aver visto rigorosamente<
JBelter
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.