2012-02-22 28 views
18

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);por qué Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

es verdadero.

Entiendo que el número entero en Java es de 32 bits y no puede ir por encima de 2^31-1, pero no puedo entender por qué agregar 1 a su MAX_VALOR da como resultado MIN_VALUE y no en algún tipo de excepción. Sin mencionar algo así como la conversión transparente a un tipo más grande, como lo hace Ruby.

¿Este comportamiento especificado en alguna parte? ¿Puedo confiar en eso?

+0

muchas buenas respuestas aquí ahora, sin embargo ahora siento curiosidad acerca de por qué preguntas "¿Puedo confiar en ello?" - ¿Por qué querrías confiar en eso? – Brian

+0

podría ser otra pregunta, --- estaba buscando algún 'iterador' que iteraría una matriz comenzando desde el elemento N, luego, después de llegar al elemento final, comenzar a iterar desde el elemento 0 al elemento N-1 --- y este entero el comportamiento podría ser útil para eso ... pero terminé con solo dos bucles diferentes –

+3

Como referencia, si desea obtener una excepción, algunas bibliotecas proporcionan métodos: [Guava] (http: //docs.guava-libraries. googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedAdd(int,%20int)) [Apache] (http://commons.apache.org/math/api- 2.2/org/apache/commons/math/util/MathUtils.html # addAndCheck (int,% 20int)) –

Respuesta

27

Porque el entero se desborda. Cuando se desborda, el siguiente valor es Integer.MIN_VALUE. Relevant JLS

Si un desbordamientos de adición de número entero, entonces el resultado es los bits de orden bajo de la suma matemática como se representa en algunos suficientemente grande formato de complemento a dos. 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 de operando.

4

La misma razón por la que la fecha cambia cuando cruzas la línea de fecha internacional: hay una discontinuidad allí. Está integrado en la naturaleza de la adición binaria.

8

es necesario entender cómo los valores enteros se representan en forma binaria, y cómo binaria obras de suma. Java usa una representación llamada complemento de dos, en la cual el primer bit del número representa su signo. Siempre que agregue 1 al entero más grande de Java, que tiene un signo de bit de 0, su signo de bit se convierte en 1 y el número se vuelve negativo.

Esta enlaces 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 a este comportamiento aquí: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

Si un número entero adición de desbordamientos, entonces el resultado es la baja - bits de orden de la suma matemática representados en un formato de complemento de 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 de operando.

Lo que significa que puede confiar en este comportamiento.

3

Cuando se agrega 3 (en binario 11) a 1 (en binario 1), debe cambiar a 0 (en binario 0) toda binaria 1 empezando por la derecha, hasta que llegamos 0, lo que se debe cambiar a 1 . Integer.MAX_VALUE tiene todos los lugares llenos con 1 por lo que quedan solamente 0 s.

21

El almacenamiento de número entero se desbordó y that is not indicated in any way, as stated in JSL 3rd Ed.:

Los operadores enteros incorporadas no indican desbordamiento positivo o negativo de ninguna manera.Los operadores enteros pueden arrojar un NullPointerException si se requiere la conversión de unboxing (§5.1.8) de una referencia nula. Aparte de eso, los únicos operadores enteros que pueden lanzar una excepción (§11) son el operador número entero división /(§15.17.2) y el operador resto entero %(§15.17.3), que arrojan un ArithmeticException si el operando de la derecha es cero, y el incremento y decremento operadores ++ (§15.15.1, §15.15.2) y -- (§15.14.3, §15.14.2), que puede lanzar una OutOfMemoryError si se requiere la conversión de boxeo (§5.1.7) 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 
4

Este es un problema bien conocido relacionado con el hecho de que los enteros se representan como two's complement abajo en la capa binaria. Cuando agrega 1 al valor máximo del número de complemento de 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 enteras, y a programadores confundidos provenientes de otros idiomas.

3

En la mayoría de los procesadores, las instrucciones aritméticas no tienen modo de falla en un desbordamiento. Establecen una bandera que debe ser revisada. Esa es una instrucción adicional, probablemente más lenta. Para que las implementaciones de idioma 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 de bibliotecas (incómodas) de Java SE 8 para arrojar en el desbordamiento, así como las operaciones sin firmar. Un comportamiento, creo que es popular en el mundo de DSP, es fijar los valores en los máximos, así que Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [no Java].

Estoy seguro de que los idiomas futuros usarán metidas de precisión arbitrarias, pero no por un tiempo todavía. Requiere un diseño de compilador más caro para ejecutarse rápidamente.

Cuestiones relacionadas