int i =132;
byte b =(byte)i; System.out.println(b);
Incompreensível. Por que a saída -124
?
Em Java, um int
é de 32 bits. A byte
é 8 bits
.
A maioria dos tipos primitivos em Java são assinados, e byte
, short
, int
, e long
são codificados em complemento de dois. (O char
tipo não está assinado e o conceito de sinal não é aplicável boolean
.)
Nesse esquema numérico, o bit mais significativo especifica o sinal do número. Se forem necessários mais bits, o bit mais significativo ("MSB") é simplesmente copiado para o novo MSB.
Portanto, se você possui byte 255
: 11111111
e deseja representá-lo como um int
(32 bits), basta copiar o 1 para a esquerda 24 vezes.
Agora, uma maneira de ler o número de complemento negativo de dois é começar com o bit menos significativo, mover para a esquerda até encontrar o primeiro 1 e depois inverter todos os bits depois. O número resultante é a versão positiva desse número
Por exemplo: 11111111
vai para 00000001
= -1
. É isso que Java exibirá como o valor.
O que você provavelmente deseja fazer é conhecer o valor não assinado do byte.
Você pode fazer isso com uma máscara de bit que exclui tudo, menos os 8 bits menos significativos. (0xff)
Assim:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Seria impresso: "Signed: -1 Unsigned: 255"
O que realmente está acontecendo aqui?
Estamos usando AND bit a bit para mascarar todos os bits de sinal estranhos (os 1 à esquerda dos 8 bits menos significativos). Quando um int é convertido em um byte, o Java retira os 24 bits mais à esquerda
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Como o 32º bit agora é o sinal em vez do 8º (e definimos o sinal como 0, o que é positivo), os 8 bits originais do byte são lidos por Java como um valor positivo.
signedByte & (0xff)
que0xff
está acontecendo aqui é que é um literal de intergeração, assim, o namedByte é promovido a um número inteiro antes da operação bit a bit ser executada.132
em dígitos ( base 10 ) está1000_0100
em bits ( base 2 ) e Java armazenaint
em 32 bits:O algoritmo para int-to-byte é truncado à esquerda; O algoritmo for
System.out.println
é o complemento de dois (o complemento de dois é se o bit mais à esquerda for1
, interprete como complemento de um negativo (bits invertidos) menos um.); AssimSystem.out.println(int-to-byte(
))
é:0000_0000_0000_0000_0000_0000_1000_0100
) [)))])1000_0100
[)))])1000_0100
))))1000_0011
)))0111_1100
))fonte
0
para positivo e1
negativo).int
para abyte
é uma conversão com perdas (isto é, informações são perdidas). Portanto, não há como convertê-lo novamente em seuint
valor original .O byte em Java é assinado, portanto, possui um intervalo de -2 ^ 7 a 2 ^ 7-1 - ou seja, -128 a 127. Como 132 está acima de 127, você termina com 132-256 = -124. Ou seja, essencialmente 256 (2 ^ 8) são adicionados ou subtraídos até que caiam no intervalo.
Para mais informações, você pode ler sobre o complemento de dois .
fonte
132 está fora do intervalo de um byte que é de -128 a 127 (Byte.MIN_VALUE a Byte.MAX_VALUE) Em vez disso, o bit superior do valor de 8 bits é tratado como o assinado, o que indica que é negativo nesse caso. Portanto, o número é 132 - 256 = -124.
fonte
aqui está um método muito mecânico sem as teorias que distraem:
Este método mais prático está de acordo com as muitas respostas teóricas acima. Portanto, aqueles que ainda estão lendo aqueles livros em Java que dizem usar o módulo, isso está definitivamente errado, pois as 4 etapas descritas acima definitivamente não são uma operação do módulo.
fonte
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdf
page 59Equação do complemento de dois:
Em Java,
byte
(N = 8) eint
(N = 32) são representados pelo complemento 2s mostrado acima.A partir da equação, um 7 é negativo para,
byte
mas positivo paraint
.fonte
geralmente nos livros, você encontra a explicação da conversão de int para byte como sendo executada pela divisão do módulo. isso não está estritamente correto, como mostrado abaixo, o que realmente acontece é que os 24 bits mais significativos do valor binário do número int são descartados, deixando confusão se o bit restante à esquerda estiver definido, que designa o número como negativo
fonte
Um algoritmo rápido que simula a maneira como funciona é o seguinte:
Como isso funciona? Olhe para a resposta daixtr . Uma implementação do algoritmo exato descrito em sua resposta é a seguinte:
fonte
Se você quiser entender isso matematicamente, como isso funciona
portanto, basicamente, os números b / w -128 a 127 serão escritos da mesma forma que seu valor decimal, acima do seu (seu número - 256).
por exemplo. 132, a resposta será 132 - 256 = - 124 ie
256 + sua resposta no número 256 + (-124) é 132
Outro exemplo
a saída será 39 44
(295 - 256) (300 - 256)
NOTA: não considerará números após o decimal.
fonte
Conceitualmente, subtrações repetidas de 256 são feitas no seu número, até que ele esteja no intervalo de -128 a +127. Portanto, no seu caso, você começa com 132 e termina com -124 em uma etapa.
Computacionalmente, isso corresponde à extração dos 8 bits menos significativos do seu número original. (E observe que o bit mais significativo desses 8 se torna o bit de sinal.)
Observe que em outros idiomas esse comportamento não está definido (por exemplo, C e C ++).
fonte
fonte