Rotate left the last 10 bits in an int

352 Views Asked by At

I need to implement a function that rotates left the last 10 bits of an int.

So if an int has value

0b 1111 0000 0000 0000 0000 1100 1100 0000

a left rotation by 2 would give us

0b 1111 0000 0000 0000 0000 1111 0000 0000

A further left rotation by 1 would give

0b 1111 0000 0000 0000 0000 1110 0000 0001
  • ptr - pointer to given int that we want to rotate
  • n - how many times we want to rotate
void leftRotateLast10Digits(int * ptr, int n) {

}

I understand how to do it if we wanted to rotate the whole int, but I'm not sure how to do it for the last 10 digits only. I think to left rotate an int, it would look something like below. But still, I don't understand how to only rotate the last 10 digits.

void leftRotate(int * ptr, int n) {
    int DROPPED_MSB;
    int INT_BITS = sizeof(int) * 8 - 1;
    int num = *ptr;

    // The effective rotation
    n %= INT_BITS;

    while(n) {
        DROPPED_MSB = (num >> INT_BITS) & 1; 

        // Left rotate num by 1 and set its dropped MSB as new LSB
        num = (num << 1) | DROPPED_MSB;
        n--;
    }
    *ptr = num;
}
2

There are 2 best solutions below

0
On

A relatively easy way to do this would be to separate the integer into two parts: the 10 bits that should be rotated and the other (upper) bits that shouldn't be rotated. Then, after rotating the appropriate part, restore the other bits using a bitwise OR operation:

void leftRotate(int* ptr, int n)
{
    int mask = 0x03FF; // Mask for lower 10 bits;
    int DROPPED_MSB;
    int INT_BITS = 10; // Only work with 10 bits
    int num = *ptr & mask; // Extract JUST low 10 bits
    int top = *ptr & ~mask; // Save all the OTHER bits
    n %= INT_BITS; // The effective rotation
    while (n) {
        DROPPED_MSB = (num >> INT_BITS) & 1;
        // Left rotate num by 1 and set its dropped MSB as new LSB
        num = (num << 1) | DROPPED_MSB;
        n--;
    }
    *ptr = num | top; // Restore the saved upper bits
}
0
On

I'm not sure how to do it for the last 10 digits only

Isolate the 10 bits from the rest.

Rotate the 10 bits (I'd skip the while loop).

"Or" the 10 bits back into the int.


(Let us use "least" rather than "last")

void leftRotateLeast10Digits(int *ptr, int n) {
  int value = *ptr;
  int ls10bits = value & 0x3FF;
  value ^= ls10bits;  // zero out the 10 LS bits.
  
  // If `n` outside [0...9] range needed
  n %= 10;
  if (n < 0) n += 10;

  // move LS bits left `n` times` and MS bits right `10-n` times.
  int rotated = (ls10bits << n) | (ls10bits >> (10-n));
  rotated &= 0x3FF;

  value |= rotated;
  *ptr = value;
}

Some additional work needed to support 16-bit int. int ls10bits --> int_least32_t ls10bits to easily handle the <<.
I'd suggest this also works for rare non-2's complement when the result is not a trap.


Tip: bit manipulations and shifts are best done with unsigned types and math rather than signed ones like int.