Java – retrieves the bits of a number
An attempt is made to retrieve bits of some numbers, such as the flag bit 00001011 of byte 11 below,
(byte) 11 >> 1 << 6 >> 5
But why is the result 10 instead of 2?
@Edit
In order to make the following method, @ Yassin hajaj's solution seems more feasible
public byte getBits(byte b,int from,int to) { // from & to inclusive return (byte) (b >> from << (8 - (to - from + 1))) >> (8 - to - 1); } getBits((byte) 11,1,2); // => 2
Or the more general @ Andreas tip,
public <T extends Number> long getBits(T n,int to) { return n.longValue() >>> from << (64 - (to - from + 1)) >>> (64 - to - 1); } getBits((byte) 11,2); // => 2
Solution
TL; Dr uses b& 6, for example (bytes) (11 & 6) See the final getbits () implementation
First, converting 11 to a byte is meaningless because the > > operator casts it back to the int value
To show you why the code is invalid, here is a program that shows all the intermediate steps:
public static void main(String[] args) { for (byte i = 0; i <= 16; i++) { int i1 = i >> 1; int i2 = i1 << 6; int i3 = i2 >> 5; System.out.printf("%3d %s -> %3d %s -> %3d %10s -> %3d %s%n",i,bin(i),i1,bin(i1),i2,bin(i2),i3,bin(i3)); } } private static String bin(int value) { String s = Integer.toBinaryString(value); return "0000000".substring(Math.min(7,s.length() - 1)) + s; }
Output:
0 00000000 -> 0 00000000 -> 0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 -> 0 00000000 -> 0 00000000 2 00000010 -> 1 00000001 -> 64 01000000 -> 2 00000010 3 00000011 -> 1 00000001 -> 64 01000000 -> 2 00000010 4 00000100 -> 2 00000010 -> 128 10000000 -> 4 00000100 5 00000101 -> 2 00000010 -> 128 10000000 -> 4 00000100 6 00000110 -> 3 00000011 -> 192 11000000 -> 6 00000110 7 00000111 -> 3 00000011 -> 192 11000000 -> 6 00000110 8 00001000 -> 4 00000100 -> 256 100000000 -> 8 00001000 9 00001001 -> 4 00000100 -> 256 100000000 -> 8 00001000 10 00001010 -> 5 00000101 -> 320 101000000 -> 10 00001010 11 00001011 -> 5 00000101 -> 320 101000000 -> 10 00001010 12 00001100 -> 6 00000110 -> 384 110000000 -> 12 00001100 13 00001101 -> 6 00000110 -> 384 110000000 -> 12 00001100 14 00001110 -> 7 00000111 -> 448 111000000 -> 14 00001110 15 00001111 -> 7 00000111 -> 448 111000000 -> 14 00001110 16 00010000 -> 8 00001000 -> 512 1000000000 -> 16 00010000
Your high bit is not cleared because it runs on the int value If you change everything to byte, you will get:
public static void main(String[] args) { for (byte i = 0; i <= 16; i++) { byte i1 = (byte)(i >> 1); byte i2 = (byte)(i1 << 6); byte i3 = (byte)(i2 >> 5); System.out.printf("%3d %s -> %3d %s -> %4d %s -> %3d %s%n",bin(i3)); } } private static String bin(byte value) { String s = Integer.toBinaryString(value & 0xFF); return "0000000".substring(s.length() - 1) + s; }
0 00000000 -> 0 00000000 -> 0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 -> 0 00000000 -> 0 00000000 2 00000010 -> 1 00000001 -> 64 01000000 -> 2 00000010 3 00000011 -> 1 00000001 -> 64 01000000 -> 2 00000010 4 00000100 -> 2 00000010 -> -128 10000000 -> -4 11111100 5 00000101 -> 2 00000010 -> -128 10000000 -> -4 11111100 6 00000110 -> 3 00000011 -> -64 11000000 -> -2 11111110 7 00000111 -> 3 00000011 -> -64 11000000 -> -2 11111110 8 00001000 -> 4 00000100 -> 0 00000000 -> 0 00000000 9 00001001 -> 4 00000100 -> 0 00000000 -> 0 00000000 10 00001010 -> 5 00000101 -> 64 01000000 -> 2 00000010 11 00001011 -> 5 00000101 -> 64 01000000 -> 2 00000010 12 00001100 -> 6 00000110 -> -128 10000000 -> -4 11111100 13 00001101 -> 6 00000110 -> -128 10000000 -> -4 11111100 14 00001110 -> 7 00000111 -> -64 11000000 -> -2 11111110 15 00001111 -> 7 00000111 -> -64 11000000 -> -2 11111110 16 00010000 -> 8 00001000 -> 0 00000000 -> 0 00000000
The problem here is the symbolic extension you get from > > Even switching to > > > will not work because > > > is still cast to int with a symbolic extension before the transition occurs
To get rid of symbolic extensions, you must use B & to convert to byte 0xff, because & will cast B to int using symbolic extension, and then bitwise and operator will delete all these bits
Of course, if you intend to use bitwise and, just use it to get the desired result, B & 0b00000110 (or B & 6)
For the same reason as above, the getbits () method does not work
The solution is still to use the bitwise and operator, but construct a bitmask from the supplied from and to values
The trick here is to use (1 < < x) - 1 to create an x-bit mask, such as 1 bit 5 - > 0b00011111. Therefore, if you want 2 to 4 (including 2 and 4), build 0x00011111 (5! Bits) and 0x00000011 (2 bits), and XOR them to get 0x00011100
public static byte getBits(byte b,int to) { if (from < 0 || from > to || to > 7) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (byte)(b & mask); }
0 00000000 -> 0 00000000 1 00000001 -> 0 00000000 2 00000010 -> 2 00000010 3 00000011 -> 2 00000010 4 00000100 -> 4 00000100 5 00000101 -> 4 00000100 6 00000110 -> 6 00000110 7 00000111 -> 6 00000110 8 00001000 -> 0 00000000 9 00001001 -> 0 00000000 10 00001010 -> 2 00000010 11 00001011 -> 2 00000010 12 00001100 -> 4 00000100 13 00001101 -> 4 00000100 14 00001110 -> 6 00000110 15 00001111 -> 6 00000110 16 00010000 -> 0 00000000
For other primitive types, overload methods:
public static byte getBits(byte value,int to) { if (from < 0 || from > to || to > 7) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (byte)(value & mask); } public static short getBits(short value,int to) { if (from < 0 || from > to || to > 15) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return (short)(value & mask); } public static int getBits(int value,int to) { if (from < 0 || from > to || to > 31) throw new IllegalArgumentException(); int mask = ((1 << (to + 1)) - 1) ^ ((1 << from) - 1); return value & mask; } public static long getBits(long value,int to) { if (from < 0 || from > to || to > 63) throw new IllegalArgumentException(); long mask = ((1L << (to + 1)) - 1) ^ ((1L << from) - 1); // <-- notice the change to long and 1L return value & mask; }