【问题标题】:Bit circular shift位循环移位
【发布时间】:2019-04-28 07:50:01
【问题描述】:

我目前正在学习按位运算,我的任务是对 4 位整数进行左旋转。

我的 4 位左旋转代码是

private static int BITS_IN_INTEGER = 4;

private static int leftRotate(int x, int n) {
  return (x << n) | (x >> (BITS_IN_INTEGER - n));
}

我想进行 4 位循环移位以在旋转后保持为 4 位,但似乎无法理解它是如何工作的。

示例:左旋转 1 位后的 10 (1010) 会给我 5 (0101) 但它给我的值是 21,这比我的 4 位多。

任何帮助我理解这个问题将不胜感激!

【问题讨论】:

  • 将 1010 向左旋转 1 得到 10100。将其向右旋转 1 将得到 101。
  • 有没有办法让它在左旋转后保持4位?

标签: java bitwise-operators bit


【解决方案1】:

如果我理解正确,你想

  • BITS_IN_INTEGER 很多位而不是32 位模拟整数。
  • 对这样的模拟整数进行旋转

目前您可以进行旋转,但不属于模拟 int 的实际 int 的高位可能会以 0 以外的值结束。示例:

intput x
0000 0000  0000 0000  0000 0000  0000 1100
                                     |____|___, emulated int
result of rotating left by n=2       |    |
0000 0000  0000 0000  0000 0000  0011 0011

正如我们所见,我们所要做的就是将模拟 int 上方的位(即 32 - BITS_IN_INTEGER 高位)设置为零。为此,我们使用逻辑“和” (&amp;)。我们需要一个掩码,在我们想要设置为零的位上具有0(任何&amp; 0 始终为0),在我们想要保留的位上具有1(任何&amp; 1 始终是任何)。

  0...0  0011 0011  ←  the result from before
& 0...0  0000 1111  ←  a mask
——————————————————
  0...0  0000 0011  ←  the masked result where unused bits are 0

要生成0...01...1BITS_IN_INTEGER 多个1s 形式的掩码,我们可以使用(1 &lt;&lt; BITS_IN_INTEGER) - 1- 110000 转换为 01111

static int BITS_IN_INTEGER = 4;
static int INTEGER_MASK = (1 << BITS_IN_INTEGER) - 1;

static int leftRotate(int x, int n) {
  return INTEGER_MASK & ((x << n) | (x >>> (BITS_IN_INTEGER - n)));
}

【讨论】:

  • 然而,右旋转不会像交换 > 那样简单,对吗?
  • 如果整个结果被INTEGER_MASK 屏蔽(因为它现在是在最新编辑之后)那么你可以交换移位运算符(在原来我只屏蔽了左移位,因为右移位不能修改未使用的位)。但是,我喜欢换一种方式来思考它:交换 n(BITS_IN_INTEGER - n) 而不是交换运算符——如果只屏蔽前一个左移,这也有效。或者,将右移实现为leftRotate(x, BITS_IN_INTEGER - n)
【解决方案2】:

这是 leftRotate()rightRotate() 实现,基于上述来自 SocowiAnswer(谢谢!)

我需要左(逆时针)右(顺时针)两个方向上模拟一个90度旋转的简单指南针(不是真正的指南针,只是一个有趣的问题)。

因此,我没有通过存储先前的方向并使用 * if / else * 或 * switch * 来弄乱代码,而是想到了 会更干净、更高效的想法,当然也很优雅。

但是,关于将掩码限制为 4 位,我遇到了同样的问题。感谢上述解决方案,我能够做到! ;)

所以假设如下:

- 北 = 1 = 0001 - 西 = 2 = 0010 - 南 = 4 = 0100 - 东 = 8 = 1000

当我需要从北转 90º 到 -> 西时,我会调用 leftRotate() 等等,直到我再次到达同一点(北)。

反之亦然,如果从北转 90º 到 -> 东我调用 rightRotate(),然后再次转南,依此类推。

这里是sn-p,希望对你有帮助:

const BITS_IN_INTEGER = 4;
const INTEGER_MASK = (1 << BITS_IN_INTEGER) - 1;

// this function rotates to left (counter clockwise) 1,2,4,8...1,2,4,8

function leftRotate(x, n) {
  return INTEGER_MASK & ((x << n) | (x >>> (BITS_IN_INTEGER - n)));
}


// this function rotates to right (clockwise)  1,8,4,2...1,8,4,2

function rightRotate(x, n) {
  return INTEGER_MASK & ((x << (BITS_IN_INTEGER - n)) | (x >>> n));
}

// Lets rotate:

console.log('--- Rotate to left (counter clockwise) 1,2,4,8...1,2,4,8...1:')

let value = 1;

for (let i = 0; i < 8; i++) {
  console.log(value);
  value = leftRotate(value, 1);
}

console.log('-- Rotate to right (counter clockwise) 1,8,4,2...1,8,4,2...1:')

for (let i = 0; i < 8; i++) {
  console.log(value);
  value = rightRotate(value, 1);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多