开发者

Finding Highest Order 1 in a Java Primitive

开发者 https://www.devze.com 2022-12-12 15:40 出处:网络
I need to find the highest order 1 in some l开发者_C百科ongs, ints, and shorts in Java. For example, if I had a char that looked like 00110101, I need a method that will return 2 (index of highest ord

I need to find the highest order 1 in some l开发者_C百科ongs, ints, and shorts in Java. For example, if I had a char that looked like 00110101, I need a method that will return 2 (index of highest order 1).

Now, I know that you can do this using a for loop like:

for(int i=0; i<8; i++)
    if((x & 1<<i) != 0) return i;
return -1;

but this is way slower than what I want to do. I know modern CPUs have instructions that do this on chip, so I want to know how I can make a call to that rather than having an explicit loop.

EDIT: Bonus points if you can just return the indices of all of the ones in the primitive.

Thanks.


Integer.numberOfLeadingZeros(i) + 1

That method uses a nice divide-and-conquer approach, copied here for your review:

public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    n -= i >>> 31;
    return n;
}


The page "Bit Twiddling Hacks" contains lots of bit hacks. One is how to find the index of the highest order bit.


I have no idea if this is faster. But it has no loop.

if(i==0) return -1;

highest=0;
if (i & 0xffff0000)
{
   highest+=16;
   i>>=16;
}
if (i & 0xff00)
{
   highest+=8;
   i>>=8;
}
if (i & 0xf0)
{
   highest+=4;
   i>>=4;
}
if (i & 0xC)
{
   highest+=2;
   i>>=2;
}
if (i & 0x2)
{
   highest+=1;
}

return highest;


I don't know about hitting a CPU instruction, but I do know that this will be a lot faster if you unroll the loop and use explicit bit masking.

Also, a char is not 8 bits... I think you might have meant a byte.


As far as I can tell, the Pentium and friends don't have an instruction ready-made for this. So the thing to do is to use a decent algorithm.

The key to getting your answer quickly is to use a binary search. You're looking at a long with 64 bits? 6 comparisons will give you your highest bit, every time.

The code works out to a big ugly tree of 64 if statements, but only a fraction of those will ever be executed, so runtime is good.

If you need sample code, I can do that. But I'd rather not.


Java being compiled into platform-independent bytecode, you cannot expect support for CPU instructions. Otherwise your code or Integer.highestOneBit() should be as fast as it gets.

0

精彩评论

暂无评论...
验证码 换一张
取 消