C:如何将2^N转换为N?

问题描述:

将范围[2^N,2 ^(N-1)-1]中的数字转换为N是一个很好的位扭曲程序是什么?C:如何将2^N转换为N?

一些例子:

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

这里是一个实现:

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

http://en.wikipedia.org/wiki/Binary_logarithm的 – kennytm 2010-11-13 18:25:34

+0

可能重复的[如何获得一个数字,是的LG2 2^K](http://stackoverflow.com/questions/2213825/ how-to-get-lg2-of-a-number-that-is-2k) – kennytm 2010-11-13 18:27:51

+0

你的意思是“范围[2^N-1,2 ^(N-1)]”? – pmg 2010-11-13 18:31:05

根据数据类型的宽度以及可用内存的大小,查找表是一种可能性。这几乎肯定是最快的方法。

有关其他方法,请参阅http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious及后续章节。

看看黑客用于计算基地2对数(或前导零计数,它们是相同的)这个页面上:http://www-graphics.stanford.edu/~seander/bithacks.html

你也可以找到有用的功能__builtin_clz(或_BitScanReverse为VS)用于x86 。

作为最普遍的方法,二分查找可能有所帮助。对于值0..31,它只需要5个阶段。

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;