表示数字x所需的位数

时间:2012-02-02 01:01:03

标签: c binary bit-manipulation

我目前正在尝试编写一种算法来确定表示数字x所需的位数。我的实现将在c。 虽然有一些捕获,但我仅限于按位运算符{〜,&,^,|,+,<<>>>}。另外,我不能使用任何类型的控制流程(if,while,for)。 我最初的方法是从左到右检查二进制数,并查找第一个' 1的出现位置。鉴于我的限制,我不知道如何处理这个问题。 我正在使用的数字可以被认为是无符号整数。所以00110只需要3位。

我想知道是否有更容易/更清洁的方法来做到这一点,我想念它? 或者,如果有人可以提供一些提示?

基本上,我试图在没有while循环的情况下实现它:

 int result = 0;
  while (x >>= 1) {
    result += 1;
  }
  return result;

5 个答案:

答案 0 :(得分:4)

http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLog

显示没有控制流程的方法。

unsigned int v;          // 32-bit value to find the log2 of 
register unsigned int r; // result of log2(v) will go here
register unsigned int shift;

r =     (v > 0xFFFF) << 4; v >>= r;
shift = (v > 0xFF  ) << 3; v >>= shift; r |= shift;
shift = (v > 0xF   ) << 2; v >>= shift; r |= shift;
shift = (v > 0x3   ) << 1; v >>= shift; r |= shift;
                                        r |= (v >> 1);
r++;

答案 1 :(得分:2)

接受的答案实际上是错误的:例如它输出5为32..63(而不是6),4为16..31(而不是5)。这就像取基数2对数并四舍五入。

正确的解决方案如下:

unsigned int v;          // 32-bit value to find the log2 of 
register unsigned int r; // result of log2(v) will go here
register unsigned int shift;

r =     (v > 0xFFFF) << 4; v >>= r;
shift = (v > 0xFF  ) << 3; v >>= shift; r |= shift;
shift = (v > 0xF   ) << 2; v >>= shift; r |= shift;
shift = (v > 0x3   ) << 1; v >>= shift; r |= shift;
                                        r |= (v >> 1);
r++;

请注意 r ++

答案 2 :(得分:2)

请尝试:

// http://www.cs.northwestern.edu/~wms128/bits.c
int check_bits_fit_in_2s_complement(signed int x, unsigned int n) {
  int mask = x >> 31;

  return !(((~x & mask) + (x & ~mask))>> (n + ~0));
}

答案 3 :(得分:1)

我有一个解决方案。 快。它计算所需的位数,即0xFFFFFFFF为32,0x00000000为0。请注意,您的C代码确实计算了最高有效位或零。

这是:

#define ISSET(x,i) (((x) >> (i)) & 1)
#define FILL(x) (-(x))
#define IF(x,y,z) ((FILL(x) & y) | (~FILL(x) & z))
#define R(x,i,y,z) (IF(ISSET(x,i),y,z))

int log2 (uint32_t x)
{
  return  R(x,31,32,
          R(x,30,31,
          R(x,29,30,
          R(x,28,29,
          R(x,27,28,
          R(x,26,27,
          R(x,25,26,
          R(x,24,25,
          R(x,23,24,
          R(x,22,23,
          R(x,21,22,
          R(x,20,21,
          R(x,19,20,
          R(x,18,19,
          R(x,17,18,
          R(x,16,17,
          R(x,15,16,
          R(x,14,15,
          R(x,13,14,
          R(x,12,13,
          R(x,11,12,
          R(x,10,11,
          R(x, 9,10,
          R(x, 8, 9,
          R(x, 7, 8,
          R(x, 6, 7,
          R(x, 5, 6,
          R(x, 4, 5,
          R(x, 3, 4,
          R(x, 2, 3,
          R(x, 1, 2,
          R(x, 0, 1, 0))))))))))))))))))))))))))))))));
}

注意:一般原则可用于其他功能。

答案 4 :(得分:-1)

好吧,我认为他需要一个第一位计数器而不是最后一位计数器。 由于该算法意味着32位整数,因此结果需要修复。

unsigned int v;          // 32-bit value to find the log2 of 
register unsigned int r; // result of log2(v) will go here
register unsigned int shift;

r =     (v > 0xFFFF) << 4; v >>= r;
shift = (v > 0xFF  ) << 3; v >>= shift; r |= shift;
shift = (v > 0xF   ) << 2; v >>= shift; r |= shift;
shift = (v > 0x3   ) << 1; v >>= shift; r |= shift;
                                        r |= (v >> 1);
return 32-r;