有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java能更有效地获取给定范围内的位吗?

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

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

现在我想得到一个4位的范围,从2的补码中这个值的第2位到第5位
我想要的范围: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) 个答案

  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. # 2 楼答案

    对于你的面具,你可以

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

    虽然准确的代码是正确的可能性很小。可能一个接一个,边缘问题,签名问题。但这是正确的吗

  3. # 3 楼答案

    免责声明:我更像是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;