问题
I know we can set any bit in the byte by using logical OR and can clear any bit by logical AND like to
val |= (1<<order_number_of_bit_to_set); //for setting some specific number of bit
and for clearing a bit
val &= ~(1<<order_number_of_bit_to_clear); // specific bit to clear
but my question is how can we check that how many and which ordered number bits are set in the byte.
for example if we have
val = 0x22;
it means that 2nd and 5th bit is set in the byte
what is the efficient, quick and shortest way to do this?
The quick solution that came to mind is to iterate through all bits and check their order and if it is set record and display the order of the bit.
But is there any other efficient way to do this?
回答1:
You should check this Built-Ins declarations you can use the function __builtin_popcount (unsigned int x) Returns the number of 1-bits in x.
回答2:
Modified From @0x499602D2's answer above:
int pos[sizeof(/* decltype(val) */)];
int bits_on = 0;
for (int i = sizeof(/* decltype(val) */) * CHAR_BIT - 1; --i;)
{
pos[i] = (val >> i) & 1;
if(pos[i]) bits_on++;
}
Gives total and position.
回答3:
The count of on bits may be optimized a bit.
int bits_on(int x)
{
x = (x & 0x55555555) + ((x>>1) & 0x55555555);
x = (x & 0x33333333) + ((x>>2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x>>8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x>>16) & 0x0000FFFF);
return x;
}
But the positions have to be found by a loop. (it is in other's answers.)
回答4:
Here's a combination of two algorithms, which iterates as many times as there are set bits:
unsigned count_low_zerobits(unsigned n) {
static const unsigned MultiplyDeBruijnBitPosition[32] =
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
return MultiplyDeBruijnBitPosition[((n & -n) * 0x077CB531U) >> 27];
}
unsigned find_bits(unsigned n, unsigned positions[]) {
unsigned c;
for (c = 0; n; c++) {
unsigned bitnum = count_low_zerobits(n); // get bit number of lowest bit
positions[c] = bitnum; // put number to positions array
n ^= 1 << bitnum; // use XOR to unset just this one bit
}
return c;
}
Reference for more info about count_low_zerobits
: an answer of question Position of least significant bit that is set .
Function find_bits
then simply calls this, puts given bit position to result array, and uses it to unset this bit using bitwise exclusive-or.
Finally, for convenience, a piece of ugly code I used to test this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned positions[128] = {0};
int testnumber = 4442344;
unsigned count = find_bits(testnumber, positions);
// non-standard, leaking one-liner for debug purposes, remove if fails to compile:
printf ("Number in binary: %s\n", itoa(testnumber, malloc(129), 2));
printf("%u bits: ", count);
for(unsigned i = 0 ; i < count ; ++i) {
printf("%u ", positions[i]);
}
printf("\n");
return 0;
}
来源:https://stackoverflow.com/questions/19106342/checking-the-number-of-bits-on-in-a-byte