'Switching the first 4 bits of a byte and the last half

I need to switch the first half and the second half of a byte: Make 0011 0101 to 0101 0011 for example

I thought it might work this way: For example, i have 1001 1100 i bitshift to the left 4 times and get 1111 1001(because if the first bit is a 1 the others become a one too) i bitshift to the right 4 times and get 1100 0000(the second half of the byte gets filled with 0s) i don't want 1111 1001 but 0000 1001 so i do 0x00001111 & 1111 1001 (which filters the frist 4 bits) to make 1111 1001 to 0000 1001 then i add everything up:

0000 1001 + 1100 0000 = 1100 1001

I got this:

bytes[i] = (byte) (( 0x00001111 & (bytes[i] >> 4)) + (bytes[i] << 4) );

here is one output: 11111111 to 00000001

I do not really understand why this is happening, I know the binary System and I think I know how bitshifting works but I can't explain this one. Sorry for bad english :)



Solution 1:[1]

Be careful with the >>> operation, which shifts the sign bits without sign extending so zero bits will fill in on the left. The problem is that it is an integer operation. The >> works the same way except it sign extends thru the int.

  int i = -1;
  i >>>= 30;
  System.out.println(i); // prints 3 as expected.

  byte b = -1;
  b >>>= 6;
  System.out.printnln(b); // prints -1 ???

The byte is still -1 because byte b = -1 was shifted as though it was an int then reassigned to a byte. So the byte remained negative. To get 3, you would need to do something that seems strange, like the following.

   byte b = -1;
   b >>>=30;
   System.out.println(b); // prints 3

So to do your swap you need to do the following;


   byte b = 0b10100110;
   b = (byte)(((b>>>4)&0xF)|(b<<4));

The 0xF mask, masks off those lingering high order bits left over from the conversion from integer back to byte.

Solution 2:[2]

I'm not sure about the syntax for bit manipulation in Java, although here's how you can do it.

bitmask = 0x1111;
firstHalf = ((bytes[i] >> 4) & bitmask);
secondHalf = ((bytes[i] & bitmask) << 4)
result = firstHalf | secondHalf;

Solution 3:[3]

I don't want 1111 1001 but 0000 1001

If so, you need to use shift right zero fill operator(>>>) instead of preserving sign of the number.

I don't think the formula found works properly.

 public byte reverseBitsByte(byte x) {
  int intSize = 8;
  byte y=0;
  for(int position=intSize-1; position>0; position--){
    y+=((x&1)<<position);
    x >>= 1;
  }
  return y;
}

Solution 4:[4]

static int swapBits(int a)  {
    // ???????? ??????? ???? ?
    int right = (a & 0b00001111);
    right= (right<<4);
    int left = (a & 0b11110000);
    left = (left>>4);
    return (right | left);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Akash Srivastav
Solution 3
Solution 4 Leonardo Alves Machado