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;
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>