Как работает bitshifting в Java?


у меня есть такое заявление:

предположим битовое значение byte x is 00101011. каков результат x>>2?

Как я могу запрограммировать его и может кто-нибудь объяснить мне, что делать?

10 54

10 ответов:

во-первых, вы можете не сдвиг byte в Java, вы можете только изменить int или long. Так что byte сначала пройдет продвижение, например

00101011 ->00000000000000000000000000101011

или

11010100 ->11111111111111111111111111010100

теперь x >> N означает (если вы рассматриваете его как строку двоичных цифр):

  • самые правые N битов отбрасываются
  • самый левый бит реплицируется столько раз, сколько необходимо дополнить результат до исходного размера (32 или 64 бит), например

00000000000000000000000000101011 >> 2 ->00000000000000000000000000001010

11111111111111111111111111010100 >> 2 ->11111111111111111111111111110101

Shift Operators

двоичный 32 бит для 00101011 и

00000000 00000000 00000000 00101011 и в результате:

  00000000 00000000 00000000 00101011   >> 2(times)
 \                                 \
  00000000 00000000 00000000 00001010

сдвигает биты 43 влево на расстояние 2; заполняет самый высокий (знак) бит с левой стороны.

результат 00001010 с десятичным значением 10.

00001010
    8+2 = 10

когда вы сдвигаете вправо 2 бита, вы отбрасываете 2 наименее значимых бита. Итак:

x = 00101011

x >> 2

// now (notice the 2 new 0's on the left of the byte)
x = 00001010

это по сути то же самое, что деление int на 2, 2 раза.

В Java

byte b = (byte) 16;
b = b >> 2;
// prints 4
System.out.println(b);

эти примеры охватывают три типа сдвигов, применяемых как к положительному, так и к отрицательному числу:

// Signed left shift on 626348975
00100101010101010101001110101111 is   626348975
01001010101010101010011101011110 is  1252697950 after << 1
10010101010101010100111010111100 is -1789571396 after << 2
00101010101010101001110101111000 is   715824504 after << 3

// Signed left shift on -552270512
11011111000101010000010101010000 is  -552270512
10111110001010100000101010100000 is -1104541024 after << 1
01111100010101000001010101000000 is  2085885248 after << 2
11111000101010000010101010000000 is  -123196800 after << 3


// Signed right shift on 626348975
00100101010101010101001110101111 is   626348975
00010010101010101010100111010111 is   313174487 after >> 1
00001001010101010101010011101011 is   156587243 after >> 2
00000100101010101010101001110101 is    78293621 after >> 3

// Signed right shift on -552270512
11011111000101010000010101010000 is  -552270512
11101111100010101000001010101000 is  -276135256 after >> 1
11110111110001010100000101010100 is  -138067628 after >> 2
11111011111000101010000010101010 is   -69033814 after >> 3


// Unsigned right shift on 626348975
00100101010101010101001110101111 is   626348975
00010010101010101010100111010111 is   313174487 after >>> 1
00001001010101010101010011101011 is   156587243 after >>> 2
00000100101010101010101001110101 is    78293621 after >>> 3

// Unsigned right shift on -552270512
11011111000101010000010101010000 is  -552270512
01101111100010101000001010101000 is  1871348392 after >>> 1
00110111110001010100000101010100 is   935674196 after >>> 2
00011011111000101010000010101010 is   467837098 after >>> 3

>> - арифметический оператор сдвига вправо. Все биты первого операнда сдвигаются на количество мест, указанных во втором операнде. Самые левые биты в результате имеют то же значение, что и самый левый бит в исходном числе. (Это так, что отрицательные числа остаются отрицательными.)

вот ваш конкретный случай:

00101011
  001010 <-- Shifted twice to the right (rightmost bits dropped)
00001010 <-- Leftmost bits filled with 0s (to match leftmost bit in original number)
public class Shift {
 public static void main(String[] args) {
  Byte b = Byte.parseByte("00101011",2);
  System.out.println(b);
  byte val = b.byteValue();
  Byte shifted = new Byte((byte) (val >> 2));
  System.out.println(shifted);

  // often overloked  are the methods of Integer

  int i = Integer.parseInt("00101011",2);
  System.out.println( Integer.toBinaryString(i));
  i >>= 2;
  System.out.println( Integer.toBinaryString(i));
 }
}

выход:

43
10
101011
1010
byte x = 51; //00101011
byte y = (byte) (x >> 2); //00001010 aka Base(10) 10

вы не можете писать двоичные литералы как 00101011 в Java, так что вы можете написать его в шестнадцатеричном виде вместо:

byte x = 0x2b;

чтобы вычислить результат x >> 2 вы можете просто написать именно это и распечатать результат.

System.out.println(x >> 2);

вы можете использовать, например, этот API, если вы хотите увидеть представление bitString ваших чисел. Uncommons Math

пример (в jruby)

bitString = org.uncommons.maths.binary.BitString.new(java.math.BigInteger.new("12").toString(2))
bitString.setBit(1, true)
bitString.toNumber => 14

edit: изменена ссылка api и добавлен небольшой пример

00101011 = 43 в десятичной системе

class test {    
    public static void main(String[] args){
       int a= 43;       
       String b= Integer.toBinaryString(a >> 2);        
       System.out.println(b);
    }   
}

выход:

101011 становится 1010