int中使用的计数位数

时间:2010-05-29 16:35:11

标签: java math binary bit-manipulation

如果您有二进制数10110,我怎么能让它返回5?例如,一个数字,告诉我们使用了多少位?下面列出了一些类似的例子:

  • 101应该返回3
  • 000000011应返回2
  • 11100应该返回5
  • 101010101应该返回9

如何以最简单的方式获得Java?我提出了以下方法,但我可以更快地完成:

public static int getBitLength(int value)
{
    if (value == 0)
    {
        return 0;
    }
    int l = 1;
    if (value >>> 16 > 0) { value >>= 16; l += 16; }
    if (value >>> 8 > 0) { value >>= 8; l += 8; }
    if (value >>> 4 > 0) { value >>= 4; l += 4; }
    if (value >>> 2 > 0) { value >>= 2; l += 2; }
    if (value >>> 1 > 0) { value >>= 1; l += 1; }
    return l;
}

11 个答案:

答案 0 :(得分:11)

最简单?

32 - Integer.numberOfLeadingZeros(value)

如果您正在寻找算法,Java API的实现者会同意您的分而治之的位移方法:

public static int numberOfLeadingZeros(int i) {
    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;
}

编辑:提醒那些信任浮点计算准确性的人,请运行以下测试工具:

public static void main(String[] args) {
    for (int i = 0; i < 64; i++) {
        long x = 1L << i;
        check(x);
        check(x-1);
    }
}

static void check(long x) {
    int correct = 64 - Long.numberOfLeadingZeros(x);
    int floated = (int) (1 + Math.floor(Math.log(x) / Math.log(2)));
    if (floated != correct) {
        System.out.println(Long.toString(x, 16) + " " + correct + " " + floated);
    }
}

第一个检测到的偏差是:

ffffffffffff 48 49

答案 1 :(得分:6)

不幸的是,没有Integer.bitLength()方法直接为您提供答案。

BigInteger存在类似的方法,因此您可以使用该方法:

BigInteger.valueOf(value).bitLength()

构造BigInteger对象会降低效率,但这只会影响数百万次。

答案 2 :(得分:2)

您想要计算数字的基数2对数 - 具体来说:

1 + floor(log2(value))

Java有一个使用base e的Math.log方法,所以你可以这样做:

1 + Math.floor(Math.log(value) / Math.log(2))

答案 3 :(得分:1)

要小心你所要求的。一种非常快速的技术是进行表查找:

int bittable [] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ... };
int numbits (int v)
{
    return bittable [v];
}

其中bittable包含每个int的条目。当然,这会带来负面价值的复杂性。更实际的方法是计算数字

的位域中的位
int bittable [16] = {0, 1, 1, 2,  1, 2, 2, 3,  1, 2, 2, 3,  2, 3, 3, 4};
int numbits (int v)
{
    int s = 0;
    while (v != 0)
    {
         s += bittable [v & 15];
         v >>= 4;
    }
    return s;
}

答案 4 :(得分:1)

您真的只想找到最高位的位置1.请参阅this page,标题为“查找整数的整数对数基数2(也就是最高位集的位置)”

答案 5 :(得分:1)

here开始,只需按位和添加即可:

int GetHighestBitPosition(int value) {
  if (value == 0) return 0;

  int position = 1;
  if ((value & 0xFFFF0000) == 0) position += 16;
  if ((value & 0xFF00FF00) == 0) position += 8;
  if ((value & 0xF0F0F0F0) == 0) position += 4;
  if ((value & 0xCCCCCCCC) == 0) position += 2;
  if ((value & 0xAAAAAAAA) == 0) position += 1;

  return position;
}

答案 6 :(得分:0)

我认为该数字的四舍五入的log_2将为您提供所需的内容。

类似的东西:

return (int)(Math.log(value) / Math.log(2)) + 1;

答案 7 :(得分:0)

int CountBits(uint value)
{
    for (byte i = 32; i > 0; i--)
    {
        var b = (uint)1 << (i - 1);
        if ((value & b) == b)
            return i;
    }
    return 0;
}

答案 8 :(得分:0)

如果您正在寻找最快的(并且没有桌子,这当然更快),这可能就是那个:

public static int bitLength(int i) {
    int len = 0;

    while (i != 0) {
        len += (i & 1);
        i >>>= 1;
    }

    return len;

}

答案 9 :(得分:0)

Integer.toBinaryString(值)。长度()

答案 10 :(得分:0)

另一种解决方案是根据API

使用length()的{​​{1}}
  

返回“逻辑大小”...索引        最高设置位...加一。

要使用BitSet,您需要创建一个数组。所以它并不像从纯BitSet开始那么简单。但是你从JDK盒中得到它 - 经过测试和支持。它看起来像这样:

int

应用于问题中的示例:

  public static int bitsCount(int i) {
    return BitSet.valueOf(new long[] { i }).length();
  }

在询问位时,我认为 bitsCount(0b101); // 3 bitsCount(0b000000011); // 2 bitsCount(0b11100); // 5 bitsCount(0b101010101); // 9 是适当的数据结构。