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?
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.
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 unArithmeticException
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 unOutOfMemoryError
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
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.
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.
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.
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.
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 0
s.