已经有一段时间了,我做了一些操作,我不确定这是否可以以更有效的方式完成。
我想要的是从一个值中获取特定范围的位
我们假设值的二进制值是: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
。我确信可能会有所改善。
答案 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;