java - ¿Por qué Integer.MAX_VALUE+1== Integer.MIN_VALUE?
integer-overflow twos-complement (8)
System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);
es verdad.
Entiendo que el número entero en Java es de 32 bits y no puede ir por encima de 2 ^ 31-1, pero no entiendo por qué agregar 1 a sus resultados MAX_VALUE en MIN_VALUE y no en algún tipo de excepción. Sin mencionar algo como la conversión transparente a un tipo más grande, como lo hace Ruby.
¿Se especifica este comportamiento en algún lugar? ¿Puedo confiar en ello?
Creo que este enlace explica lo que está viendo: http://en.wikipedia.org/wiki/Two''s_complement
Cuando agrega 3
(en binario 11
) a 1 (en binario 1
), debe cambiar a 0
(en binario 0
) todos los binarios 1
comenzando desde la derecha, hasta que obtenga 0, que debe cambiar a 1
. Integer.MAX_VALUE
tiene todos los lugares llenos con 1
por lo que solo quedan 0
s.
Debe comprender cómo se representan los valores enteros en forma binaria y cómo funciona la suma binaria. Java usa una representación llamada complemento de dos, en la que el primer bit del número representa su signo. Cada vez que agregue 1 al mayor entero java, que tiene un signo de bit de 0, su signo de bit se convierte en 1 y el número se vuelve negativo.
Este enlace explica con más detalles: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java
-
La especificación del lenguaje Java trata este comportamiento aquí: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2
Si una adición de enteros se desborda, el resultado son los bits de orden inferior de la suma matemática, tal como se representa en un formato de complemento a dos suficientemente grande. Si se produce un desbordamiento, entonces el signo del resultado no es el mismo que el signo de la suma matemática de los dos valores del operando.
Lo que significa que puedes confiar en este comportamiento.
El almacenamiento de enteros se desborda y eso no se indica de ninguna manera, como se indica en JSL 3rd Ed. :
Los operadores enteros incorporados no indican desbordamiento o subdesbordamiento de ninguna manera. Los operadores enteros pueden lanzar una
NullPointerException
si se requiere la conversión unboxing (§5.1.8) de una referencia nula. Aparte de eso, los únicos operadores de enteros que pueden lanzar una excepción (§11) son el operador de división de enteros/
(§15.17.2) y el operador de resto de enteros%
(§15.17.3) , que arrojan unaArithmeticException
si el derecho el operando de mano es cero, y los operadores de incremento y decremento++
( §15.15.1 , §15.15.2 ) y--
( §15.14.3 , §15.14.2 ), que pueden lanzar unOutOfMemoryError
si la conversión de boxeo (§5.1.7) es obligatorio y no hay suficiente memoria disponible para realizar la conversión.
Ejemplo en un almacenamiento de 4 bits:
MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)
MAX_INT + 1:
0111+
0001
----
1000
En la mayoría de los procesadores, las instrucciones aritméticas no tienen modo de fallar en un desbordamiento. Establecen una bandera que debe ser marcada. Esa es una instrucción extra, así que probablemente sea más lento. Para que las implementaciones de lenguaje sean lo más rápidas posible, los idiomas se especifican con frecuencia para ignorar el error y continuar. Para Java el comportamiento se especifica en el JLS . Para C, el lenguaje no especifica el comportamiento, pero los procesadores modernos se comportarán como Java.
Creo que hay propuestas para (incómodo) bibliotecas de Java SE 8 para lanzar en desbordamiento, así como operaciones sin firmar. Un comportamiento, creo que popular en el mundo DSP, es fijar los valores en los valores máximos, por lo que Integer.MAX_VALUE + 1 == Integer.MAX_VALUE
[no Java].
Estoy seguro de que los idiomas futuros usarán intenciones de precisión arbitrarias, pero no por un tiempo todavía. Requiere un diseño de compilador más caro para ejecutarse rápidamente.
Este es un problema bien conocido relacionado con el hecho de que los enteros se representan como http://en.wikipedia.org/wiki/Two''s_complement dos en la capa binaria. Cuando agrega 1 al valor máximo de un número de complemento a dos, obtiene el valor mínimo. Honestamente, todos los enteros se comportaron de esta manera antes de que existiera Java, y cambiar este comportamiento para el lenguaje Java habría agregado más sobrecarga a las matemáticas de enteros, y a los programadores confundidos provenientes de otros lenguajes.
La misma razón por la que la fecha cambia cuando se cruza la línea de fecha internacional: existe una discontinuidad allí. Está integrado en la naturaleza de la adición binaria.
Porque el entero se desborda. Cuando se desborda, el siguiente valor es Integer.MIN_VALUE
. JLS relevante
Si una adición de enteros se desborda, el resultado son los bits de orden inferior de la suma matemática, tal como se representa en un formato de complemento a dos suficientemente grande. Si se produce un desbordamiento, entonces el signo del resultado no es el mismo que el signo de la suma matemática de los dos valores del operando.