web-dev-qa-db-fra.com

pourquoi Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

est vrai.

Je comprends cet entier en Java est 32 bits et ne peut pas dépasser 231-1, mais je ne comprends pas pourquoi ajouter 1 à son MAX_VALUE résulte en MIN_VALUE et non dans une sorte d'exception. Sans mentionner quelque chose comme une conversion transparente vers un type plus grand, comme Ruby le fait.

Ce comportement est-il spécifié quelque part? Puis-je m'y fier?

27
Oleg Mikheev

Parce que l'entier déborde. Lorsqu'il déborde, la valeur suivante est Integer.MIN_VALUE. JLS pertinent

Si un ajout d'entier déborde, alors le résultat est les bits de poids faible de la somme mathématique tels que représentés dans un format de complément à deux suffisamment grand. En cas de débordement, le signe du résultat n'est pas le même que le signe de la somme mathématique des deux valeurs d'opérande.

28
Bozho

Le stockage entier est débordé et ce n'est pas indiqué en aucune façon, comme indiqué dans JSL 3ème éd. :

Les opérateurs entiers intégrés n'indiquent en aucun cas un débordement ou un débordement. Les opérateurs entiers peuvent lancer un NullPointerException si une conversion de décodage (§5.1.8) d'une référence nulle est requise. En dehors de cela, les seuls opérateurs entiers qui peuvent lever une exception (§11) sont l'opérateur de division entier /(§15.17.2) et l'opérateur de reste entier %(§15.17.3) , qui lance un ArithmeticException si l'opérande de droite est nul, et les opérateurs d'incrémentation et de décrémentation ++ ( §15.15.1 , §15.15.2 ) et -- ( §15.14. , §15.14.2 ), qui peut lancer un OutOfMemoryError si conversion de boxe (§5.1.7 ) est requis et la mémoire disponible est insuffisante pour effectuer la conversion.

Exemple dans un stockage 4 bits:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000
25
falsarella

Vous devez comprendre comment les valeurs entières sont représentées sous forme binaire et comment fonctionne l'addition binaire. Java utilise une représentation appelée complément à deux, dans laquelle le premier bit du nombre représente son signe. Chaque fois que vous ajoutez 1 au plus grand Java Entier, qui a un signe de bit de 0, puis son signe de bit devient 1 et le nombre devient négatif.

Ce lien explique avec plus de détails: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-Java

-

La spécification de langage Java Java traite ce comportement ici: http://docs.Oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

Si un ajout d'entier déborde, alors le résultat est les bits de poids faible de la somme mathématique tels que représentés dans un format de complément à deux suffisamment grand. En cas de débordement, le signe du résultat n'est pas le même que le signe de la somme mathématique des deux valeurs d'opérande.

Ce qui signifie que vous pouvez compter sur ce comportement.

8
ARRG

Sur la plupart des processeurs, les instructions arithmétiques n'ont aucun mode de défaut en cas de débordement. Ils ont mis un drapeau qui doit être vérifié. C'est une instruction supplémentaire donc probablement plus lente. Pour que les implémentations de langage soient aussi rapides que possible, les langues sont fréquemment spécifiées pour ignorer l'erreur et continuer. Pour Java le comportement est spécifié dans le JLS . Pour C, le langage ne spécifie pas le comportement, mais les processeurs modernes se comportera comme Java.

Je crois qu'il y a des propositions pour (maladroit) Java SE 8 bibliothèques à lancer sur le débordement, ainsi que des opérations non signées. Un comportement, je crois populaire dans le monde DSP, est de fixer les valeurs au maximums, donc Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [pas Java].

Je suis sûr que les futures langues utiliseront des nombres de précision arbitraires, mais pas encore pour un moment. Nécessite une conception de compilateur plus coûteuse pour fonctionner rapidement.

7
Tom Hawtin - tackline

La même raison pour laquelle la date change lorsque vous franchissez la ligne de date internationale: il y a là une discontinuité. Il est intégré dans la nature de l'addition binaire.

4
duffymo

Il s'agit d'un problème bien connu lié au fait que les entiers sont représentés comme complément à deux au niveau de la couche binaire. Lorsque vous ajoutez 1 à la valeur maximale d'un complément à deux, vous obtenez la valeur minimale. Honnêtement, tous les entiers se sont comportés de cette façon avant Java existait, et changer ce comportement pour le langage Java aurait ajouté plus de surcharge aux mathématiques entières, et les programmeurs confus venant à partir d'autres langues.

4
Craig H

Lorsque vous ajoutez 3 (en binaire 11) à 1 (en binaire 1), vous devez passer à 0 (en binaire 0) tous binaires 1 en partant de la droite, jusqu'à ce que vous obteniez 0, que vous devez remplacer par 1. Integer.MAX_VALUE a tous les lieux remplis de 1 donc il ne reste que 0s.

3
IProblemFactory