Pergunta

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

é verdade.

Eu entendo que o inteiro em Java é de 32 bits e não pode ir acima de 2 31 -1, mas não consigo entender por que adicionar 1 a seu MAX_VALUE resulta em MIN_VALUE e não em algum tipode exceção.Sem mencionar algo como a conversão transparente para um tipo maior, como o Ruby faz.

Este comportamento está especificado em algum lugar?Posso confiar nisso?

Foi útil?

Solução

Porque o número inteiro estourou.Quando transborda, o próximo valor é Integer.MIN_VALUE. JLS relevante

Se uma adição de inteiro estourar, o resultado serão os bits de ordem inferior da soma matemática representada em algum formato de complemento de dois suficientemente grande.Se ocorrer estouro, o sinal do resultado não é o mesmo que o sinal da soma matemática dos dois valores de operando.

Outras dicas

O armazenamento inteiro é estourado e isso não é indicado de qualquer forma, conforme declarado na JSL 3ª Ed. :

Os operadores inteiros integrados não indicam estouro ou estouro negativo de forma alguma. Operadores inteiros podem lançar um NullPointerException se unboxing conversão (§5.1 8) de uma referência nula é necessária. Fora isso, os únicos operadores inteiros que podem lançar uma exceção (§11) são o / do operador de divisão de inteiros (§15.17.2) e o operador de resto inteiro % (§15.17.3) , que lança um ArithmeticException se o operando à direita for zero, e os operadores de incremento e decremento ++ ( §15.15.1 , §15.15.2 ) e -- ( §15. 14.3 , §15.14.2 ), que pode lançar um OutOfMemoryError se conversão de boxing (§ 5.1.7) é necessário e não há memória suficiente disponível para realizar a conversão.

Exemplo em um armazenamento de 4 bits:

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

MAX_INT + 1:

 0111+
 0001
 ----
 1000

Você deve entender como os valores inteiros são representados na forma binária e como a adição binária funciona. Java usa uma representação chamada complemento de dois, em que o primeiro bit do número representa seu sinal. Sempre que você adiciona 1 ao maior inteiro java, que tem um sinal de bit 0, seu sinal de bit torna-se 1 e o número torna-se negativo.

Este link explica com mais detalhes: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

-

A especificação da linguagem Java trata esse comportamento aqui: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

Se uma adição de inteiro estourar, o resultado serão os bits de ordem inferior da soma matemática representada em algum formato de complemento de dois suficientemente grande. Se ocorrer estouro, o sinal do resultado não é o mesmo que o sinal da soma matemática dos dois valores de operando.

O que significa que você pode confiar nesse comportamento.

Na maioria dos processadores, as instruções aritméticas não têm modo de falha em um estouro.Eles definem um sinalizador que deve ser verificado.Essa é uma instrução extra, provavelmente mais lenta.Para que as implementações de linguagem sejam o mais rápidas possível, as linguagens são frequentemente especificadas para ignorar o erro e continuar.Para Java, o comportamento é especificado no JLS .Para C, a linguagem não especifica o comportamento, mas os processadores modernos se comportarão como Java.

Acredito que existam propostas para bibliotecas Java SE 8 (estranhas) para gerar overflow, bem como operações não assinadas.Um comportamento, acredito que seja popular no mundo DSP, é fixar os valores no máximo, então Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [não Java].

Tenho certeza de que as linguagens futuras usarão ints de precisão arbitrária, mas não por enquanto.Requer um design de compilador mais caro para ser executado rapidamente.

O mesmo motivo pelo qual a data muda quando você cruza a linha internacional de data: há uma descontinuidade aí.Está embutido na natureza da adição binária.

This is a well known issue related to the fact that Integers are represented as two's complement down at the binary layer. When you add 1 to the max value of a two's complement number you get the min value. Honestly, all integers behaved this way before java existed, and changing this behavior for the Java language would have added more overhead to integer math, and confused programmers coming from other languages.

When you add 3 (in binary 11) to 1 (in binary 1), you must change to 0 (in binary 0) all binary 1 starting from the right, until you got 0, which you should change to 1. Integer.MAX_VALUE has all places filled up with 1 so there remain only 0s.

Cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483647, -2147483646, -2147483645, ... and so forth to the far most right again and on and on, its nature of summing machine on this bit depth.

Some examples:

int a = 2147483647;

System.out.println(a);

gives: 2147483647

System.out.println(a+1);

gives: -2147483648 (cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483648, -2147483647, -2147483646, ... and so fores to the far most right again and on and on, its nature of summing machine on this bit depth)

System.out.println(2-a); 

gives:-2147483645 (-2147483647+2 seems mathematical logical)

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

gives: 2147483647 (-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 some loop described in previous answers)

System.out.println(2*a);

gives: -2 (2147483647+2147483647 -> -2147483648+2147483646 again mathematical logical)

System.out.println(4*a);

gives: -4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647 -> -2-2 (according to last answer) -> -4)`

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top