Question

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

est vrai.

Je comprends que l'entier en java est 32 bits et ne peut pas aller au-dessus de 231-1, mais je ne comprends pas pourquoi en ajoutant 1 à son MAX_VALUE résulte en MIN_VALUE Et pas dans une sorte d'exception. Ne mentionnant pas quelque chose comme une conversion transparente en un type plus grand, comme Ruby.

Ce comportement est-il spécifié quelque part? Puis-je en compter?

Était-ce utile?

La solution

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

Si un ajout entier déborde, alors le résultat est les bits de faible ordre de la somme mathématique représentés dans un format de complément de deux suffisamment grand. Si un débordement se produit, 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.

Autres conseils

Le stockage entier est débordé et Cela n'est indiqué en aucune façon, comme indiqué dans JSL 3e éd.:

Les opérateurs entiers intégrés n'indiquent en aucune façon le débordement ou le sous-flux. Les opérateurs entiers peuvent lancer un NullPointerException Si la conversion de déballage (§5.1.8) d'une référence nulle est requise. En dehors de cela, les seuls opérateurs entiers qui peuvent lancer une exception (§11) sont l'opérateur de division entier / (§15.17.2) et l'opérateur reste entier % (§15.17.3), qui jette un ArithmeticException Si l'opérande de droite est nul et les opérateurs d'incrément et de décréments ++(§15.15.1, §15.15.2) et --(§15.14.3, §15.14.2), qui peut lancer un OutOfMemoryError Si la conversion de boxe (§5.1.7) est requis et il n'y a pas suffisamment de mémoire disponible 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'ajout binaire. Java utilise une représentation appelée complément de Two, dans laquelle le premier bit du nombre représente son signe. Chaque fois que vous ajoutez 1 au plus grand entier Java, qui a un signe de 0, alors son signe de bits devient 1 et le nombre devient négatif.

Ces liens expliquent avec plus de détails: http://www.cs.grinnell.edu/~rebelsky/espresso/readings/binary.html#integers-in-java

--

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

Si un ajout entier déborde, alors le résultat est les bits de faible ordre de la somme mathématique représentés dans un format de complément de deux suffisamment grand. Si un débordement se produit, 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 pas de mode à reprocher sur un débordement. Ils ont défini un drapeau qui doit être vérifié. C'est une instruction supplémentaire donc probablement plus lent. Pour que les implémentations de la langue soient aussi rapidement 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, la langue ne spécifie pas le comportement, mais les processeurs modernes se comporteront comme Java.

Je crois qu'il existe des propositions de bibliothèques (maladroites) Java SE 8 pour lancer un débordement, ainsi que des opérations non signées. Un comportement, je crois que populaire dans le monde du DSP, est de serrer les valeurs au maximum, donc Integer.MAX_VALUE + 1 == Integer.MAX_VALUE pas java].

Je suis sûr que les futures langues utiliseront des INT de précision arbitraire, mais pas encore un certain temps. Nécessite une conception de compilateurs 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 une discontinuité là-bas. Il est intégré à 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 vers le bas à la couche binaire. Lorsque vous ajoutez 1 à la valeur maximale du numéro de complément d'un Two, vous obtenez la valeur min. Honnêtement, tous les entiers se sont comportés de cette façon avant l'existence de Java, et changer ce comportement pour le langage Java aurait ajouté plus de frais généraux aux mathématiques entiers, et des programmeurs confus venant d'autres langues.

Lorsque vous ajoutez 3 (en binaire 11) à 1 (en binaire 1), vous devez changer pour 0 (en binaire 0) Tous les binaires 1 à partir de la droite, jusqu'à ce que vous ayez 0, que vous devriez changer pour 1. Integer.MAX_VALUE a tous les endroits remplis de 1 donc il ne reste que 0s.

Cause du débordement et du nombre de natures à deux conformes se déroulent sur "Second Loop", nous étions en position la plus droite 2147483647 et après avoir résumé 1, nous sommes apparus à la position la plus gauche -2147483648, l'incrémentation suivante va -2147483647, -2147483646, -2147483645, ... et ainsi de suite à l'extrême droite à nouveau et encore, sa nature de la machine de sommation sur cette profondeur de bit.

Quelques exemples:

int a = 2147483647;

System.out.println(a);

Donne: 2147483647

System.out.println(a+1);

Donne: -2147483648 (Cause de débordement et du nombre de natures à deux conformes se poursuit sur "Second Loop", nous étions en position la plus droite 2147483647 et après avoir résumé 1, nous sommes apparus à la position la plus gauche -2147483648, l'incrémentation suivante va -2147483648, - - 2147483647, -2147483646, et assure ainsi le plus loin à nouveau à nouveau et à nouveau, sa nature de la machine à résumé sur cette profondeur de bit)

System.out.println(2-a); 

Donne: -2147483645 (-2147483647 + 2 semble logique mathématique)

System.out.println(-2-a);

Donne: 2147483647 (-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 décrit dans les réponses précédentes)

System.out.println(2*a);

Donne: -2 (2147483647 + 2147483647 -> -2147483648 + 2147483646 à nouveau mathématique logique)

System.out.println(4*a);

Give: -4 (2147483647 + 2147483647 + 2147483647 + 2147483647 -> -2147483648 + 2147483646 + 2147483647 + 2147483647 -> -2-2 (selon Last Answer) -> -4) '

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top