Valeur de i pour (i == -i && i! = 0) pour retourner true dans Java

J’ai la condition suivante if

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

Quelle valeur de i retournerai true pour cette condition en Java?

Je ne peux pas penser à une telle valeur de considérer la notation de complément à deux en Java.

J’aimerais aussi avoir une preuve algébrique de la réponse à cette condition (dans le contexte de Java)?

La seule valeur int pour laquelle il fonctionne est Integer.MIN_VALUE .

C’est parce que les entiers sont annulés en utilisant le complément à deux .

En utilisant

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

vous voyez que Integer.MIN_VALUE est

 10000000000000000000000000000000 

Prendre la valeur négative se fait en échangeant d’abord 0 et 1 , ce qui donne

 01111111111111111111111111111111 

et en ajoutant 1 , ce qui donne

 10000000000000000000000000000000 

Comme vous pouvez le voir dans le lien que j’ai donné, Wikipedia mentionne le problème avec les nombres les plus négatifs et précise que c’est la seule exception:

Le nombre le plus négatif dans le complément à deux est parfois appelé “le nombre étrange”, car c’est la seule exception.

Bien sûr, vous avez le même phénomène pour Long.Min_Value si vous le stockez dans une variable long .

Notez que cela est uniquement dû aux choix effectués concernant le stockage binary des ints en Java . Une autre (mauvaise) solution pourrait par exemple être de nier en changeant simplement le bit le plus significatif et en laissant les autres bits inchangés, ceci aurait évité ce problème avec MIN_VALUE mais aurait fait 2 valeurs 0 différentes et une arithmétique binary compliquée (comment ont incrémenté par exemple?).

La valeur que vous recherchez est Integer.MIN_VALUE .


J’aimerais aussi avoir une preuve algébrique de la réponse à cette condition (dans le contexte de Java)?

C’est hors sujet pour Stack Exchange. Mais vous pouvez le faire à partir de la définition des entiers Java ( JLS 4.2 )

“Les types intégraux sont octet, short, int et long, dont les valeurs sont des entiers à deux complémentation signés à 8 bits, 16 bits, 32 bits et 64 bits …”

et

“Les valeurs des types intégraux sont des entiers dans les plages suivantes … Pour int, de -2147483648 à 2147483647 inclus”

et la définition de l’opérateur Java unaire ‘-‘ ( JLS 15.15.4 ):

“Pour les valeurs entières, la négation est la même que la soustraction de zéro. Le langage de programmation Java utilise la représentation de complément à deux pour les entiers et la plage de valeurs de complément à deux n’est pas symésortingque. même nombre maximum négatif: un dépassement se produit dans ce cas, mais aucune exception n’est levée Pour toutes les valeurs entières x, -x est égal à (~ x) +1. “

En plus des réponses données jusqu’à présent …

Il y a quatre valeurs au total

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

Les valeurs emballées sont déballées et sont également vraies pour cette expression.

Note: Documents Math.abs.

public static int abs (int a)

Retourne la valeur absolue d’une valeur int. Si l’argument n’est pas négatif, l’argument est renvoyé. Si l’argument est négatif, la négation de l’argument est renvoyée.

Notez que si l’argument est égal à la valeur de Integer.MIN_VALUE, la valeur int représentable la plus négative, le résultat est la même valeur, qui est négative.

et

statique public long abs (long a)

Renvoie la valeur absolue d’une valeur longue. Si l’argument n’est pas négatif, l’argument est renvoyé. Si l’argument est négatif, la négation de l’argument est renvoyée.

Notez que si l’argument est égal à la valeur de Long.MIN_VALUE, la valeur longue représentable la plus négative, le résultat est la même valeur, qui est négative.

Il est surprenant que Math.abs puisse renvoyer un nombre négatif. Cela se produit soit parce que a) il n’y a pas de valeurs positives pour -MIN_VALUE dans ces cas-là b) l’exécution du calcul a pour résultat un débordement.

Ce qui est également intéressant, c’est pourquoi Byte.MIN_VALUE, Short.MIN_VALUE ne le font pas. C’est parce que le - change le type en int pour ceux-ci et donc pas de débordement.

Character.MIN_VALUE n’a pas de problème car il vaut 0.

Float.MIN_VALUE et Double.MIN_VALUE ont une signification différente. Ce sont la plus petite valeur représentable supérieure à zéro. Ils ont donc des valeurs négatives valables qui ne sont pas elles-mêmes.

Comme les autres l’ont mentionné, cela n’est rempli que par Integer.MIN_VALUE . En ce qui concerne la preuve, permettez-moi de vous proposer une explication plus facile à comprendre que dans le binary (même si elle est toujours enracinée dans cela).

Notez que Integer.MIN_VALUE est égal à -2^31 ou -2147483648 et Integer.MAX_VALUE est égal à 2^31-1 ou 2147483647 . -Integer.MIN_VALUE est 2^31 , qui est maintenant trop grand pour un entier (puisque MAX_VALUE est passé), provoquant ainsi un dépassement d’entier, le rendant à nouveau Integer.MIN_VALUE . C’est le seul entier qui le fait puisque MIN_VALUE est le seul nombre sans équivalent négatif à part 0.

Preuve algébrique provisoire, en utilisant l’arithmétique modulo 2^32 :

i == -i peut être réécrit en 2 * i == 0 (en ajoutant i deux côtés), ou i << 1 == 0 .

Cette équation a deux solutions de la forme i == 0 >> 1 , à savoir 0b et 10000000000000000000000000000000b obtenues en décalant 0 ou 1 sur la gauche.

La solution i == 0 étant exclue, il rest la solution i == 100000000000000000000000000000000b .

Peut-être que ce n’est pas trop éducatif, mais au lieu de penser que vous pourriez exécuter ce code:

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

pour voir qu'il imprime

 -2147483648 -2147483648 

infiniment 🙂