【问题标题】:Rotate left the last 10 bits in an int将 int 中的最后 10 位向左旋转
【发布时间】:2020-07-09 20:24:37
【问题描述】:

我需要实现一个向左旋转 int 的最后 10 位的函数。

所以如果一个 int 有值

0b 1111 0000 0000 0000 0000 1100 1100 0000

向左旋转 2 会得到我们

0b 1111 0000 0000 0000 0000 1111 0000 0000

进一步向左旋转 1 会得到

0b 1111 0000 0000 0000 0000 1110 0000 0001
  • ptr - 指向我们要旋转的给定 int 的指针
  • n - 我们要旋转多少次
void leftRotateLast10Digits(int * ptr, int n) {

}

如果我们想旋转整个 int,我知道该怎么做,但我不确定如何仅对最后 10 位数字进行操作。我想左旋转一个int,它看起来像下面这样。但是,我仍然不明白如何只旋转最后 10 位数字。

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;
}

【问题讨论】:

  • 你可以用 0b1111111111111111111110000000000 取起始数字和 & 它。现在你有了不能改变的位。您可以使用 0b1111111111 进行逆运算和 & 起始编号。这 10 位需要旋转。你知道该怎么做。最后 |两个数字一起。
  • 1) 所以旋转只涉及 10 个最低有效位,我理解正确吗? 2)int INT_BITS = sizeof(int) * 8 - 1; 似乎构建了一个适用于每种架构的通用功能。是要求吗?可以接受 4 字节整数的假设吗?
  • scy17,您是否希望此轮换适用于 n &gt; 9n &lt; 0
  • scy17 注意:int INT_BITS = sizeof(int) * 8 - 1; n %= INT_BITS; 是有问题的代码。我希望n %= INT_BITS + 1; 和更多人能够处理n &lt; 0

标签: c bitwise-operators byte-shifting


【解决方案1】:

我不知道如何只处理最后 10 位数字

将这 10 位与其他位隔离开来。

旋转 10 位(我会跳过 while 循环)。

将这 10 位“或”回int


(让我们使用“最少”而不是“最后”)

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;
}

需要一些额外的工作来支持 16 位 intint ls10bits --> int_least32_t ls10bits 轻松处理&lt;&lt;
当结果不是陷阱时,我建议这也适用于罕见的非 2 补码。


提示:位操作和移位最好用 unsigned 类型和数学来完成,而不是像 int 这样的 signed 类型。

【讨论】:

    【解决方案2】:

    一个相对简单的方法是将整数分成两部分:应该旋转的 10 位和不应该旋转的其他(高位)位。然后,在旋转适当的部分后,使用按位或运算恢复其他位:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多