【问题标题】:left Rotate algorithm binary value in c在c中左旋转算法二进制值
【发布时间】:2024-01-30 13:55:02
【问题描述】:

我正在尝试左旋转二进制值:

int left_side=0;
    for (int i = 0; i < n; i++)
    {         
        left_side = left_side | (  ( number & ( 1<<BITS-i )) >> (BITS+i+1)-n  );

    }

BITS表示二进制长度,n为旋转距离。
示例: 1000 ,并且 n=1 表示解为:0001。

当我旋转它(从左到右)时我不明白的一些原因,让我们以数字 253 为例,它的二进制序列是 11111101 和 n=3(距离),我的代码的结果二进制序列是 101(即 5)。
为什么答案不是 7?在这个循环中我错过了什么? 谢谢。

【问题讨论】:

  • 也不要忘记您正在尝试转换 signed int。注意符号位。你不想使用unsigned int吗?
  • 我无法重现您的错误结果left_side = 5。对我来说,结果是left_side = 1(这也是错误的)。 Try it yourself.

标签: c bit-manipulation bitwise-operators


【解决方案1】:

您想将特定amount 的位数n 向左旋转。

因此,您必须使用n &lt;&lt; amount 将您的号码向左移动,并将左边的位放在右边。这是通过使用右移将位 [0-amount[ 放入 [NUMBER_BITS-amount,NUMBER_BITS[` 位来完成的。

例如,如果您的号码是uint32_t,您可以使用以下代码(或轻松将其调整为其他类型)。

uint32_t RotateLeft(uint32_t n, int amount)  { 
    return (n << amount)|(n >> (8*sizeof(uint32_t) - amount)); 
}

【讨论】:

    【解决方案2】:

    我认为有两种方法:

    1. 旋转 1 位 n
    2. 只旋转一次n % BITS

    旋转“结束”,因此我们可以将n 的每个 BITSth(第 8 个)倍数取模为 0,以防有人想要旋转 100 次。我认为第二种方法更容易理解、实现和阅读,如果可以循环一次,为什么要循环 100 次?

    算法:

    我将使用 8 位进行演示,即使 int is minimum 16 bits。原来的 MSB 用一个点标记。

    .11110000 rl 2 == 110000.11

    嗯,发生了什么事? 2 位向右,其余 (BITS - 2) 向左。这只是左移和右移“组合”。

    a = .11110000 << 2 == 110000.00
    b = .11110000 >> (BITS - 2) == 000000.11
    c = a | b
    c == 110000.11
    

    很简单,不是吗?请记住首先使用n % BITS,然后使用unsigned 类型。

    unsigned int rotateLeft(unsigned int number, int n) {
        n %= BITS;
        unsigned int left = number << n;
        unsigned int right = number >> (BITS - n);
        return left | right;
    }
    

    【讨论】:

    • 谢谢,同样的逻辑也适用于有符号整数?
    • No, accroding to en.wikipedia.org/wiki/… "当在有符号类型上执行时,结果在技术上是未定义的并且依赖于编译器,但是大多数编译器将执行算术移位,导致空白被符号填充左操作数的位。”所以通常负数会在 MSB 中保留 1,从而在换档时污染一切。我确定你不想要这个。