From: mike-yue on
For example,

0x03 has 2 bits sets.
0x04 has 1 bits set.
0x07 has 3 bits sets.

Suppose we get a really big array, like

unsigned char ucarray[1024*1024*1024];

then what is the best way to count the number of all set bits(no
memory limit)?


To discuss it here because it was an interview question, and I didn't
find the best way. Only method I got was counting the set bits in one
element, and then jump to next element.

Here is a function to count set bits in one unsigned char:

int bits(unsigned char v) {
return (v==0)?0:bits1((unsigned char)v&(v-1))+1;
}

or:

int bits(unsigned char v) {
int count;
for(count = 0; v != 0; count++, v &= (v-1));
return count;
}

Two other supplementary methods may do helps:
1. using macro to replace the upper functions
2. copy the array content to another same memory size unsigned long
array, and count the set bits based on unsigned long instead of
unsigned char.

All the methods here base on array element, not a WHOLE memory block.
I am wondering if there is a way to operate a whole block of memory,
and count bit sets of the memory block.

Many thanks for your attention, and any opinions would be appreciated.

From: Ivan Novick on
On Dec 28, 12:55 pm, mike-yue <needpass...(a)gmail.com> wrote:
> For example,
>
> 0x03 has 2 bits sets.
> 0x04 has 1 bits set.
> 0x07 has 3 bits sets.
>
> Suppose we get a really big array, like
>
> unsigned char ucarray[1024*1024*1024];
>
> then what is the best way to count the number of all set bits(no
> memory limit)?
>
If you haven't check this site yet, please do:
http://graphics.stanford.edu/~seander/bithacks.html

AFAIK its the best resource for bit manipulation algorithms (interview
questions) :)

Regards,
Ivan Novick
http://www.0x4849.net
From: Francis Glassborow on
mike-yue wrote:
> For example,
>
> 0x03 has 2 bits sets.
> 0x04 has 1 bits set.
> 0x07 has 3 bits sets.
>
> Suppose we get a really big array, like
>
> unsigned char ucarray[1024*1024*1024];
>
> then what is the best way to count the number of all set bits(no
> memory limit)?
>
>
> To discuss it here because it was an interview question, and I didn't
> find the best way. Only method I got was counting the set bits in one
> element, and then jump to next element.
>
> Here is a function to count set bits in one unsigned char:
>
> int bits(unsigned char v) {
> return (v==0)?0:bits1((unsigned char)v&(v-1))+1;
> }
>
> or:
>
> int bits(unsigned char v) {
> int count;
> for(count = 0; v != 0; count++, v &= (v-1));
> return count;
> }
>
> Two other supplementary methods may do helps:
> 1. using macro to replace the upper functions
> 2. copy the array content to another same memory size unsigned long
> array, and count the set bits based on unsigned long instead of
> unsigned char.
>
> All the methods here base on array element, not a WHOLE memory block.
> I am wondering if there is a way to operate a whole block of memory,
> and count bit sets of the memory block.
>
> Many thanks for your attention, and any opinions would be appreciated.
>


Well my first thought is to create an array of 256 ints and populate it
with the required values:

int bitcounts[256] = {0, 1, 2, 1, 2, 2, 3 and so on

now I would use that as a lookup table, e.g.

long bitcount(int * source, size_t number){
long result(0);
for(size_t i(0); i != number; ++i) result += bitcounts[source[i]];
return result;
}
From: Richard Heathfield on
Francis Glassborow said:

<snip>

> Well my first thought is to create an array of 256 ints and populate it
> with the required values:
>
> int bitcounts[256] = {0, 1, 2, 1, 2, 2, 3 and so on

UCHAR_MAX + 1, surely?

(One would of course write a program to generate such a table, rather than
compose it by hand.)

> now I would use that as a lookup table, e.g.
>
> long bitcount(int * source, size_t number){
> long result(0);
> for(size_t i(0); i != number; ++i) result += bitcounts[source[i]];
> return result;
> }

The OP actually said "unsigned char array", so I'm puzzled by int * source.

I'd have done it like this:

unsigned long bitcount(unsigned char *source, size_t number)
{
unsigned long result = 0;
while(number--)
{
result += bitcounts[*source++];
}
return result;
}

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
From: Ivan Novick on
On Dec 29, 4:38 am, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> mike-yue wrote:
> > For example,
>
> > 0x03 has 2 bits sets.
> > 0x04 has 1 bits set.
> > 0x07 has 3 bits sets.
>
> > Suppose we get a really big array, like
>
> > unsigned char ucarray[1024*1024*1024];
>
> > then what is the best way to count the number of all set bits(no
> > memory limit)?
>
> > To discuss it here because it was an interview question, and I didn't
> > find the best way. Only method I got was counting the set bits in one
> > element, and then jump to next element.
>
> > Here is a function to count set bits in one unsigned char:
>
> > int bits(unsigned char v) {
> > return (v==0)?0:bits1((unsigned char)v&(v-1))+1;
> > }
>
> > or:
>
> > int bits(unsigned char v) {
> > int count;
> > for(count = 0; v != 0; count++, v &= (v-1));
> > return count;
> > }
>
> > Two other supplementary methods may do helps:
> > 1. using macro to replace the upper functions
> > 2. copy the array content to another same memory size unsigned long
> > array, and count the set bits based on unsigned long instead of
> > unsigned char.
>
> > All the methods here base on array element, not a WHOLE memory block.
> > I am wondering if there is a way to operate a whole block of memory,
> > and count bit sets of the memory block.
>
> > Many thanks for your attention, and any opinions would be appreciated.
>
> Well my first thought is to create an array of 256 ints and populate it
> with the required values:
>
> int bitcounts[256] = {0, 1, 2, 1, 2, 2, 3 and so on
>
> now I would use that as a lookup table, e.g.
>
> long bitcount(int * source, size_t number){
> long result(0);
> for(size_t i(0); i != number; ++i) result += bitcounts[source[i]];
> return result;
>
> }

Could you do it in half the time if your lookup table consisted of all
the combinations in 16 bits, and then you looped and checked 2 bytes
at a time?

int bitcounts[65536] = { ..... }

Regards,
Ivan Novick
http://www.0x4849.net