07/06/2021

[Java] Circular right and left bit shifts

When I touch bit problems I always remember why we introduced so many abstraction layers between us and them.

The problem we have is as follows, given a number perform a circular shift of all its bits right by a given amount.

Example: 110 with a circular right shift of 2 becomes 101

Provide also a similar method that does a left shift, example 110 with a circular left shift of 2 becomes 011

Now in a perfect world, we can notice that the result is simply the bit by bit combination of both right AND left shift operations on the number. In our example 110 with a right shift of 2:

  • 110 with a simple right shift of 2 becomes: 001
  • what we dropped off the right would need to go the left of our result, we can get it with a left shift of (length - shift) positions: 100
  • combine the two bit by bit and we get the result: 101

Similarly we can do the same for left shift.

All good, however, due to how things are represented in Java we run into some issues:

  • right shift operator >> preserves sign, we need to use bitwise operator instead >>> 
  • for left shift instead the logic is the same, therefore there is only a << operator
  • integers are 32 bits, which is 4 bytes, when we define which input in bits we are handling, we need to convert it to the integer representing that 32 bit sequence, for example 10000000000000000000000000000000 (1 followed by 31 zeros) is 2147483648 which you will recognize as being just after the maximum allowed integer, therefore NOT an acceptable integer, however a perfectly fine 32 bit sequence. In other words, considering signed integers, that sequence would be -0 which does not exist
  • negative numbers are represented using two's complement, therefore -3 is represented not as 1_then_29_zeros_11 but start_30_ones_01 instead which breaks our logic since the bitwise shift operators would move bits set to 1 which we instead assume are set to 0 instead when we work on negative numbers

It might be therefore worth it to work with Byte objects rather than integers in order to use purely unsigned bit representations.

You can check my implementation of rightRotateShiftBits and leftRotateShiftBits on my Gist along with some tests in BitUtilsJTests.

No comments:

Post a Comment

With great power comes great responsibility