简体   繁体   中英

Bit twiddling in C: how to convert from 2^N to N?

What is a good bit-twiddling routine to convert a number in the range [2^N,2^(N-1)-1] to N?

Some examples:

  • f(1) -> 0
  • f([2-3]) -> 1
  • f([4-7]) -> 2
  • f([8-15]) -> 3

Here is one implementation:

uint f(uint num)
{
    for (uint shifts = 0; num; shifts++) 
        num >>= 1;
    return (shifts - 1);
}

Depending on how wide your data-type is, and how much memory you have available, a lookup-table is one possibility. It's almost certainly the fastest approach.

For other approaches, see http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious , and the subsequent sections.

As most general approach, binary search may help. For values 0..31 it need only 5 stages.

y = 0;
if(x >= 0x10000<<y) y += 0x10;
if(x >= 0x100<<y) y += 0x08;
if(x >= 0x10<<y) y += 0x04;
if(x >= 0x4<<y) y += 0x02;
if(x >= 0x2<<y) y += 0x01;

Take a look at hacks for computing base 2 logarithm (or leading zero count, they are the same) on this page: http://www-graphics.stanford.edu/~seander/bithacks.html

You could also find useful the function __builtin_clz (or _BitScanReverse for VS) for x86.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM