Почему 11010100 << 1 равно 110101000, а не 10101000?

40

Почему, когда я пытаюсь сдвинуть биты для 11010100 2 , результат будет 110101000 2 , а не 10101000 2 .

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

Я пытаюсь сделать это:

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

Но если выходное значение больше 128, все идет в минус, что логично. Как сделать так, чтобы количество бит не менялось?

Ярошенко Ярослав
источник
4
Целочисленная арифметика всегда выполняется на ints или longs.
Том Хотин -
34
Вы используете целые числа, длиной 32 бита. Почему вы ожидаете, что результат будет усечен до 8 бит?
Джамон
1
байт = исправит это.
Perdi Estaquel

Ответы:

61

Давайте сделаем это один шаг за один раз.

  1. Integer.parseInt("11010100", 2)- это значение int 212. Это, кстати, ненужно; вы можете просто написать: 0b11010100.

  2. 0b11010100 << 1такой же, как 0b110101000и 424.

  3. Затем вы бросаете его в байт (byte)(0b11010100 << 1). Биты после первых 8 все обрезаются, что оставляет 0b10101000, что составляет -88. Минус да, потому что в Java подписаны байты.

  4. Затем вы молча преобразуете этот -88 обратно в int, так как присваиваете ему значение int. Остается -88, что означает, что все старшие биты равны 1.

Следовательно, окончательное значение -88.

Если вы хотите видеть 168вместо этого (который является точно такими же битами, но показан без знака вместо подписанного), следует использовать обычную хитрость & 0xFF, которая устанавливает все биты, кроме первых 8, в 0, таким образом гарантируя положительное число:

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
источник
19
Он хранит значение в int a, так что если у вас есть & 0xFF, то вам не нужно вообще разыгрывать. int a = (0b11010100<< 1) & 0xFF;
Mooing Duck
9

Если вы хотите установить на 0 все биты выше, чем нижние 8 бит, вы можете использовать побитовое И:

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

Вывод:

10101000
Эран
источник
6

Попробуйте что-то вроде этого:

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

toUnsignedInt был представлен в Java SE 8.

красновато-коричневый
источник