Por que 11010100 << 1 é igual a 110101000, e não 10101000?

40

Por que, quando tento mudar os bits para 11010100 2 , o resultado é 110101000 2 , e não 10101000 2 .

int a = Integer.parseInt("11010100", 2) << 1;

Eu tento fazer isso:

int a = (byte)(Integer.parseInt("11010100", 2) << 1);

Mas se o valor de saída for maior que 128, tudo será menos, o que é lógico. Como posso fazer esse número de bits não mudar?

Yaroshenko Yaroslav
fonte
4
A aritmética inteira é sempre feita em ints ou longs.
Tom Hawtin - tackline em
34
Você está usando números inteiros, com 32 bits. Por que você esperaria que o resultado fosse truncado para 8 bits?
jhamon 20/02
11
byte a = ... irá corrigi-lo.
Perdi Estaquel

Respostas:

61

Vamos dar um passo de cada vez.

  1. Integer.parseInt("11010100", 2)- este é o valor int 212. A propósito, isso é desnecessário; você pode apenas escrever: 0b11010100.

  2. 0b11010100 << 1é o mesmo que 0b110101000e é 424.

  3. Você, então, lançá-lo para um byte: (byte)(0b11010100 << 1). Os bits além dos 8 primeiros são cortados, deixando 0b10101000, que é -88. Menos, sim, porque em java bytes são assinados.

  4. Em seguida, você converte -88 silenciosamente em int, ao atribuí-lo a um valor int. Permanece -88, o que significa que todos os bits superiores são 1s.

Portanto, o valor final é -88.

Se você deseja ver 168(que são exatamente os mesmos bits, mas mostrados sem sinal em vez de assinar), o truque usual é usar & 0xFF, que define todos os bits, exceto os primeiros 8 a 0, garantindo assim um número positivo:

byte b = (byte) (0b11010100 << 1);
System.out.println(b); // -88. It is not possible to print 168 when printing a byte.
int asUnsigned = b & 0xFF;
System.out.println(asUnsigned); // 168.

// or in one go:

System.out.println(((byte) (0b11010100 << 1)) & 0xFF); // 168
rzwitserloot
fonte
19
Ele está armazenando o valor int a, por isso, se você tiver & 0xFF, não precisará lançar nada. int a = (0b11010100<< 1) & 0xFF;
Mooing Duck
9

Se você deseja definir como 0 todos os bits mais altos que os 8 bits inferiores, pode usar AND bit a bit:

int a = (Integer.parseInt("11010100", 2) << 1) & 0xff;
System.out.println (Integer.toString(a,2));

Resultado:

10101000
Eran
fonte
6

Tente algo como isto:

int anInt = Integer.parseInt("11010100", 2) << 1;
int asUnsignedInt= Byte.toUnsignedInt((byte) anInt);

toUnsignedInt foi introduzido no Java SE 8.

Puce
fonte