C 计算整数的二进制表示

C 计算整数的二进制表示,c,C,我必须计算整数的二进制表示的长度。 我试过这样的方法: int binaryLength(int n) { int i = 32; while (i > 0) { if (n >> i & 1) break; else i--; } return i; } 但当我有9(1001)这样的数字时,此函数返回32。您可以通过执行以下操作来查找长度: length =

我必须计算整数的二进制表示的长度。 我试过这样的方法:

int binaryLength(int n)
{
      int i = 32;
      while (i > 0)
      {
           if (n >> i & 1) break;
           else i--;
       }
       return i;
 }

但当我有9(1001)这样的数字时,此函数返回32。

您可以通过执行以下操作来查找长度:

length = ceil(log(N + 1)/log(2));

这就是长度,即log base 2的上限N。因为我记不起log base 2函数名,所以我在做上面的等效操作。您需要使用N+1来正确解释N是2的直接幂,因此需要一个额外的位来表示它。示例N=8=1000(二进制)。8的对数基2是3,3的上限是3,但9的对数基2是3.16993,3.16993的上限是4

如果我是你,我会放弃循环方法

这是我所知道的最快的方法-专门为32位
int
编码。它不适用于负整数(负整数的位模式无论如何都依赖于平台)。为64位
int
添加一个额外的行;这个计划应该是显而易见的

int binaryLength(int n)
{
    int i = 0; // the minimum number of bits required.
    if (n >= 0x7FFF) {n >>= 16; i += 16;}
    if (n >= 0x7F) {n >>= 8; i += 8;}
    if (n >= 0x7) {n >>= 4; i += 4;}
    if (n >= 0x3) {n >>= 2; i += 2;}
    if (n >= 0x1) {n >>= 1; i += 1;}
    return i;
}

首先,考虑使用<代码>无符号INT/COM>——我怀疑这正是你想要的。然后一个明智的方法是将输入的数字一直向下移动,直到它为零。比如:

unsigned int binaryLength(unsigned int n)
{
      unsigned int i = 0;
      while (n >>= 1)
      {
         ++i;
      }

      return i;
}
有很多更快的方法(您可以简单地使用查找表等),但这似乎接近您最初的方法。

From

一个N位二补数字系统可以表示每个整数 在范围内−(2N − 1) to+(2N) − 1.− 1)

这应该适用于负数和正数

int binaryLength(int n)
{
    int num       = n;
    int nMinus1   = 0;
    int i         = 0;

    if(0 > num)
        num = -num;

    if(0 >= n)
    {
        while(((1<<nMinus1)-1) <= num)
        {
            nMinus1++;
        }
    } else {
        while((1<<nMinus1) <= num)
        {
            nMinus1++;
        }
    }

    i = nMinus1+1;

    printf("Number %d binary length %d\n", n, i);

    return 0;
}

为什么不能使用
sizeof(int)*8
?不能将32位整数移位32。好吧,这是未定义的行为,但通常它的行为类似于移位模32,也就是说,实际上是移位0。由于数字(9)设置了最低有效位,循环在第一次迭代时中断。试着从31岁开始。这和我从31岁开始是一样的31@Lundin:1)没有神奇的数字。这就是字符的作用。2)
int
不能使用所有位。对于负值,由实现定义。对于小于33位的
int
,这是未定义的行为。这种方法的问题是
log
可能低估结果。浮点的不精确性足以使结果“消失”。此外,
log
的效率也很低。有很多有效的方法来计算位,新的CPU甚至有硬件支持it@Bathsheba我不明白为什么,但是函数关闭了1:
n>>=1
计算为“新移位”值,如果你明白我的意思的话。所以你跳过一个
++i
。顺便说一句,我的UB注释是废话,因为你正在“一个接一个”地移位。负整数将返回32,因为第一位(符号位)是1。是否需要首先确定这一点?(例如,
if((int)这确实不适用于负数,所以我不明白为什么需要
int
(特别是关于右移的评论,这当然对有符号的数字更糟糕)@unwind:主要是因为OP就是这样。酷猫之间有一种运动,不使用
无符号
,并在使用点限制有符号的。所以我不想弄乱类型。如果你不允许负值,你可以很好地使用无符号类型。它们允许传递带正负值的有符号整数也一样,所以没什么变化。不知道你说的“酷猫”是什么意思,但一般来说,在移位任意值时,优秀的程序员更喜欢无符号整数。这可能与其他定义了编码和运算的语言有所不同。为什么这么复杂?@LưuVĩnhPhúc:很抱歉,我没有理解。我想同时处理正数和负数。不需要。有更有效的方法哦,是的。但我的想法不同。如果数字是-1,那么它将以32位整数的形式存储为0xFFFFFF。但实际上,您可以将它写成两位,即11,假设一位表示符号,一位表示值。我认为问题是找到存储数字所需的最小位数。我不这么认为,这是关于“二进制表示”表示负数的最小位是另一个问题,这取决于有符号数的格式
Number 0 binary length 2                                                                                                                                            
Number 1 binary length 2                                                                                                                                            
Number -1 binary length 3                                                                                                                                           
Number 9 binary length 5                                                                                                                                            
Number -9 binary length 5