我想找到设置为1
的最高有效位。我已经尝试了从&
到对从1
到31
的所有位进行"或"运算的所有可能方法,但都不起作用。
就像1000000
一样,我想要7
。
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html#numberOfLeadingZeros%28int%29你想要32 - Integer.numberOfLeadingZeros(value)
这样的东西。
我遇到的最巧妙的实现——三次迭代和一次表查找。
unsigned int msb32(unsigned int x)
{
static const unsigned int bval[] =
{ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
unsigned int base = 0;
if (x & 0xFFFF0000) { base += 32/2; x >>= 32/2; }
if (x & 0x0000FF00) { base += 32/4; x >>= 32/4; }
if (x & 0x000000F0) { base += 32/8; x >>= 32/8; }
return base + bval[x];
}
虽然有一个可以接受的答案,但我有另一种分享方式,我认为这更容易。
如果您想使用按位操作,方法如下。基本上,我对整数进行右移,直到它变为零。不需要戴口罩。
private static int mostSignificantBit(int myInt){
int i = 0;
while (myInt != 0) {
++i;
myInt >>>= 1;
}
return i;
}
另一种方法是用数学方法计算:
private static int mostSignificantBit(int myInt){
if (myInt == 0) return 0; // special handling for 0
if (myInt < 0) return 32; // special handling for -ve
return (int)(Math.log(myInt)/Math.log(2)) +1;
}
如果你坚持直接使用位运算符,你可以尝试这样的方法:
private int mostSignificantBit(int myInt){
int mask = 1 << 31;
for(int bitIndex = 31; bitIndex >= 0; bitIndex--){
if((myInt & mask) != 0){
return bitIndex;
}
mask >>>= 1;
}
return -1;
}
我们将掩码初始化为1 << 31
,因为这表示1后面跟着31个0。我们使用该值来测试索引31(第32个点)是否为1。当我们用myInt
and
这个值时,我们得到一个0,除非在myInt
中设置了相应的位。如果是这种情况,我们返回bitIndex
。如果没有,那么我们将遮罩向右移动1,然后重试。我们重复,直到我们没有位置可以移位,在这种情况下,这意味着没有设置任何位(也许你想在这里抛出一个异常,而不是返回-1)。
注意,这将为1
返回值0
,为64
返回值6
(二进制的1000000
)。如果你愿意,你可以调整。还要注意,我使用了无符号右移运算符,而不是有符号右移。这是因为这里的目的是处理原始比特,而不是它们的签名解释,但在这种情况下这并不重要,因为所有负值都将在移位发生之前的循环的第一次迭代中终止。
逐次逼近将迭代次数减少到五个循环:
unsigned int mostSignificantBit(uint32_t val) {
unsigned int bit = 0;
/* 4 = log(sizeof(val) * 8) / log(2) - 1 */
for(int r = 4; r >= 0 ; --r) {
unsigned shift = 1 << r; /* 2^r */
uint32_t sval = val >> shift;
if (sval) {
bit += shift;
val = sval;
}
}
return bit;
}
也许不是最有效的,但这应该有效::
public int firstBit(int i) {
return i < 0 ? 31 : i == 0 ? 0 : Integer.toString(i, 2).length();
}
只是添加另一种方法
public static int mostSignificantBit(int b) {
for (int i = 1 << 30, j = 0; i > 0; i /= 2, j++) {
if ((b & i) > 0) {
return 31-j;
}
}
return -1;
}
只需使用Long或Integer类的numberOfTrailingZeros(value)方法。
对于Little Endian格式:
((yourByte & yourBitMask) >> msbIndex) && 0x01
if( value | 0x40 ) return 7;
else if( value | 0x20 ) return 6;
else if( value | 0x10 ) return 5;
else if( value | 0x8 ) return 4;
else if( value | 0x4 ) return 3;
else if( value | 0x2 ) return 2;
else if( value | 0x1 ) return 1;