删除特定索引处的位

时间:2014-01-21 12:52:33

标签: java bit-manipulation bit bit-shift

我基本上试图从特定索引处的整数中删除一个位。也就是说,我不想取消/清除这一点;我实际上想剥离它,以便每个更高的位向下移动,替换其位置的相应位。在视觉上,可以将其与从数组中删除元素或从字符串中删除字符进行比较。

为了清楚起见,举例说明:

1011011 (original number)
    ^ index = 2
0101111 (result)

10000000000000000000000000000001
^ index = 31
00000000000000000000000000000001

1111111111111111111111111111110
                              ^ index = 0
0111111111111111111111111111111

充满自信,我开始转移一些位,并提出了以下Java方法......

public static int removeBit(int num, int i) {
    int out = (num >>> (i + 1)) << i;
    out  |= (num << (32 - i)) >>> (32 - i);
    return out;
}

......除了一些极端情况外几乎总是有效:

10000000000000000000000000000001 (= Integer.MAX_VALUE - 1)
^ index = 31, results in:
10000000000000000000000000000001

1011011
      ^ index = 0, results in:
1111111

换句话说,如果索引是0或31(最小或最高位),我的方法将输出垃圾。

我似乎无法绕过它,这就是我要问的原因:如何删除32位整数中的任意位?

我特别希望用Java(最小的内存和CPU消耗)来实现最高效的方法,因为这个操作必须运行至少几百万次。这就是为什么像“将它转换为字符串,删除字符并将其转换回来”之类的东西是不可能的。

3 个答案:

答案 0 :(得分:2)

正如评论中所解释的那样,班次计数翻到了&gt; = 32,这造成了麻烦。

无论如何,让我们找到一种方法。

首先考虑两个“碎片”,低碎片(在原始位置复制,可能在0 ... 31位长之间的任何位置)和高碎片(向下移动一个,也可以在0 ... 31位长之间)。碎片的总长度始终为31。

小件的面具显而易见:~(-1 << i)

这使得高件的面具显而易见:~lowmask << 1。无论如何,高的部分都会移动,这样就可以转移。

现在剩下的就是把它们和OR一起拿出来,你就得到了

static int removeBit(int x, int i)
{
    int mask = ~(-1 << i);
    return (x & mask) | ((x >>> 1) & ~mask);
}

抛弃双重否定:

static int removeBit(int x, int i)
{
    int mask = -1 << i;
    return (x & ~mask) | ((x >>> 1) & mask);
}

答案 1 :(得分:1)

只需掩盖所需的位,无需来回移动

public static int removeBit(int num, int index) {
    int mask = (1 << index) - 1;
    return ((num & ((~mask) << 1)) >>> 1) | (num & mask);
}

public static int removeBit(int num, int index) {
    int mask = (1 << index) - 1;
    return ((num >>> 1) & ~mask) | (num & mask);
}

答案 2 :(得分:1)

如果使用最少数量的指令很重要,对于这种位混洗,通常最好计算需要切换的位,然后使用异或来应用它。同样在这里,与哈罗德的解决方案相比,这节省了一条指令:

static int removeBit(int x, int i)
{
    int mask = -1 << i;
    return ((x ^ (x >>> 1)) & mask) ^ x;
}

static int removeBit(int x, int i)
{
    return (((x ^ (x >>> 1)) >>> i) << i) ^ x;
}