获得给定范围的位更有效?

时间:2014-10-22 05:24:34

标签: java bit-manipulation twos-complement

已经有一段时间了,我做了一些操作,我不确定这是否可以以更有效的方式完成。

我想要的是从一个值中获取特定范围的位 我们假设值的二进制值是:0b1101101

现在我希望在它的二进制补码中从该值的第二位到第五位获得一个4位范围。
我想要的范围:0b1011
两个补码中的值:-5

这是我的代码,有些想法我正在做的事情:

public int bitRange(int value, int from, int to) {

    // cut the least significant bits
    value = value >> from;

    // create the mask
    int mask = 0;
    for (int i = from; i <= to; i++) {
        mask = (mask << 1) + 1;
    }

    // extract the bits
    value = value & mask;

    // needed to check the MSB of the range
    int msb = 1 << (to - from);

    // if MSB is 1, XOR and inverse it
    if ((value & msb) == msb ) {
        value = value ^ mask;           
        value = ~value;
    }

    return value;

}

现在我想知道这是否可以更有效?特别是动态掩码的创建和范围的MSB的检查,能够转换位范围。另一点是,正如user3344003正确指出的那样,如果范围是1位,则输出将是-1。我确信可能会有所改善。

3 个答案:

答案 0 :(得分:1)

对于你的面具,你可以像

那样

int mask = 0xffffffff >> 32-(to-from);

虽然确切代码正确的可能性很小。可能是一个边缘问题,签署问题。但它是在正确的轨道上?

答案 1 :(得分:1)

这是你的面具:

int mask = 0xffffffff >>> 32 - (to - from + 1);

由于符号位为>>>,您必须使用1

另一种解决方案可能是存储可能最多31个值的掩码:

private static int[] MASKS = new int[31];
static {
    MASKS[0] = 1;
    for (int i = 1; i < MASKS.length; i++)
        MASKS[i] = (MASKS[i - 1] << 1) + 1;
}

使用你的面具:

int mask = MASKS[to - from];

您可以对msb掩码执行相同操作,只将可能的值存储在静态数组中,而不必在方法中计算它。

答案 2 :(得分:0)

免责声明:我更多的是C或C ++程序员,我知道不同语言的按位运算符之间有一些小写。但在我看来,这可以通过利用在将负值向右移动时产生的算术移位在一行中完成,其中一个将移入符号扩展。

public int bitRange(int value, int from, int to) {
  int waste = 31 - to;
  return (value << waste) >> (waste + from);
}

击穿:

int a = 31 - to;    // the number of bits to throw away on the left  
int b = value << a; // shift the bits to throw away off the left of the value
int c = a + from;   // the number of bits that now need to be thrown away on the right
int d = b >> c;     // throw bits away on the right, and extend the sign on the left
return d;