Count bits used in int

后端 未结 11 1397
梦谈多话
梦谈多话 2020-12-30 15:54

If you have the binary number 10110 how can I get it to return 5? e.g a number that tells how many bits are used? There are some likewise examples listed below:

相关标签:
11条回答
  • 2020-12-30 16:33

    From here, a way to do it with just bitwise-and and addition:

    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;
    }
    
    0 讨论(0)
  • 2020-12-30 16:37

    You really just want to find the position of the highest bit that is a 1. See this page, under the heading "Finding integer log base 2 of an integer (aka the position of the highest bit set)".

    0 讨论(0)
  • 2020-12-30 16:38

    Be careful what you ask for. One very fast technique is to do a table lookup:

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

    where bittable contains an entry for every int. Of course that has complications for negative values. A more practical way would be to count the bits in bitfields of the number

    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;
    }
    
    0 讨论(0)
  • 2020-12-30 16:38
    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;
    }
    
    0 讨论(0)
  • 2020-12-30 16:42

    Easiest?

    32 - Integer.numberOfLeadingZeros(value)
    

    If you are looking for algorithms, the implementors of the Java API agree with your divide-and-conquer bitshifting approach:

    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;
    }
    

    Edit: As a reminder to those who trust in the accuracy of floating point calculations, run the following test harness:

    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);
        }
    }
    

    The first detected deviation is:

    ffffffffffff 48 49
    
    0 讨论(0)
  • 2020-12-30 16:45

    Unfortunately there is no Integer.bitLength() method that would give you the answer directly.

    An analogous method exists for BigInteger, so you could use that one:

    BigInteger.valueOf(value).bitLength()
    

    Constructing the BigInteger object will make it somewhat less efficient, but that will only matter if you do it many millions of times.

    0 讨论(0)
提交回复
热议问题