473,405 Members | 2,300 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Counting 'on' bits in a byte?

Trying to return the number of 'on' bits in a byte:
'a' = 01100001 = 3 on bits, etc...

I'm just adding a bit-wise AND ('&' against octal 1) to a counter called
'bits', then shifting my byte 1 bit to the right; do this 8 times.

This works, but I was curious if there's some more effective formula
without looping or recursion? That seems like an awful lot of code, but
I can't think of a better way.
int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
Jul 18 '06 #1
13 7226

John wrote:
int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
Two things

1. Right shifting signed types == bad
2. Is this really the bottleneck in your application?

But if you know you're dealing with bytes and have the space just use
an 8x8 lookup table. Failing that here's a hint: BitCount(x&15) +
BitCount(x>>4) == BitCount(x) for 8-bit unsigned "x".

Tom

Jul 18 '06 #2
John (in 0G*******************@tornado.ohiordc.rr.com) said:

| Trying to return the number of 'on' bits in a byte:
| 'a' = 01100001 = 3 on bits, etc...
|
| I'm just adding a bit-wise AND ('&' against octal 1) to a counter
| called 'bits', then shifting my byte 1 bit to the right; do this 8
| times.
|
| This works, but I was curious if there's some more effective formula
| without looping or recursion? That seems like an awful lot of
| code, but I can't think of a better way.
|
| int BitCount(char c)
| {
| int ctr;
| int bits = 0;
| for (ctr = 0; ctr < 8; ctr++) {
| bits += c & 0001;
| c >>= 1;
| }
| return (bits);
| }

int BitCount(unsigned char c)
{ int bits = 0;
do bits += c & 1; while (c >>= 1);
return bits;
}

The fast, no-loop method would involve pre-storing counts in a
256-element array so that you could code:

int BitCount(unsigned char c)
{ static unsigned char count[] = { 0,1,1,2,1, /* .. */ ,8 };
return count[(unsigned char)c];
}

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Jul 18 '06 #3
Morris Dovey (in 93*************@news.uswest.net) said:

....ugly stuff. I meant to lose the cast. The compiler knows how to
handle the subscript.

| int BitCount(unsigned char c)
| { static unsigned char count[] = { 0,1,1,2,1, /* .. */ ,8 };
return count[c];
| }

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Jul 18 '06 #4
Morris Dovey wrote:
int BitCount(unsigned char c)
{ int bits = 0;
do bits += c & 1; while (c >>= 1);
return bits;
}
bah

int bitcount(unsigned char c)
{
unsigned char s;
s = (c & 0x11);
s += ((c >1) & 0x11);
s += ((c >2) & 0x11);
s += ((c >3) & 0x11);
return (s&15) + (s>>4);
}

More fun :-). Can work in even more parallel on bigger words.

int bitcount(unsigned c)
{
unsigned s;
s = (c & 0x1111);
s += ((c >1) & 0x1111);
s += ((c >2) & 0x1111);
s += ((c >3) & 0x1111);
s = (s + (s >8)) & 255;
return (s&15) + (s>>4);
}

Compared to the other approach which requires on average 15 ANDs,
shifts, additions and XORs this approach only requires 6 ANDs, 5 shifts
and 5 additions. It's also constant time (in the realtime sense).

:-)

Tom

Jul 18 '06 #5
John wrote:
>
Trying to return the number of 'on' bits in a byte:
I can't think of a better way.

int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
unsigned bit_count(unsigned n)
{
unsigned count;

for (count = 0; n != 0; n &= n - 1) {
++count;
}
return count;
}

--
pete
Jul 18 '06 #6
"pete" <pf*****@mindspring.comwrote in message
news:44***********@mindspring.com...
John wrote:
>>
Trying to return the number of 'on' bits in a byte:
>I can't think of a better way.

int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}

unsigned bit_count(unsigned n)
{
unsigned count;

for (count = 0; n != 0; n &= n - 1) {
++count;
}
return count;
}

--
pete
/* Got tableshiftcast from Chris Torek IIRC. */

static const char nbits[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};

int
tC_tableshiftcast (unsigned long n)
{

return nbits[(unsigned char) n] +
nbits[(unsigned char) (n >8)] +
nbits[(unsigned char) (n >16)] +
nbits[(unsigned char) (n >24)];
}

/*
Some hacky things for 64 bit versions:
*/
#include <assert.h>
#include <limits.h>

#if (~(USHRT_MAX+UCHAR_MAX) != ~USHRT_MAX-UCHAR_MAX)
#error(no two's-complement);
#endif

typedef unsigned long long bitboard;

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >

Matt Taylor's implementation of the de Bruijn bitscan:

From a post on CCC:
http://chessprogramming.org/cccsearc...?art_id=306789

Subject : Re: There is huge potential to improve further
Posted by : Matt Taylor on July 16, 2003 at 22:44:43

Which is indirectly a reference to this work:

"Using de Bruijn Sequences to Index a 1 in a Computer Word"

Charles E.Leiserso
Harald Prokop
Keith H, Randall

MIT Laboratory for Computer Science, Cambridge, MA 02139, USA
July 7, 1998

http://supertech.csail.mit.edu/papers/debruijn.ps

The reset option is an obvious and useful addition implemented
by Gerd Isenberg
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< < */

const int lsz64_tbl[64] =
{
0, 31, 4, 33, 60, 15, 12, 34,
61, 25, 51, 10, 56, 20, 22, 35,
62, 30, 3, 54, 52, 24, 42, 19,
57, 29, 2, 44, 47, 28, 1, 36,
63, 32, 59, 5, 6, 50, 55, 7,
16, 53, 13, 41, 8, 43, 46, 17,
26, 58, 49, 14, 11, 40, 9, 45,
21, 48, 39, 23, 18, 38, 37, 27,
};

unsigned int bitScanAndReset(bitboard & bb)
{
assert(UINT_MAX >= 0xffffffff);
bitboard b = bb ^ (bb - 1);
bb &= (bb - 1);
unsigned int fold = (unsigned) ((b & 0xffffffff) ^ (b >32));
return lsz64_tbl[(fold * 0x78291ACF) >(32 - 6)];
}
unsigned int bitScan(bitboard & bb)
{
assert(UINT_MAX >= 0xffffffff);
bitboard b = bb ^ (bb - 1);
unsigned int fold = (unsigned) ((b & 0xffffffff) ^ (b >32));
return lsz64_tbl[(fold * 0x78291ACF) >(32 - 6)];
}

// return index 0..63 of MSB
// -1023 if passing zero

unsigned int bitScanReverse(bitboard bb)
{
union {
double d;
struct {
unsigned int mantissal : 32;
unsigned int mantissah : 20;
unsigned int exponent : 11;
unsigned int sign : 1;
};
} ud;
ud.d = (double)(bb & ~(bb >32));
return ud.exponent - 1023;
}

/*popCount()
*a noniterative population count of 1 bits in a quadword
*
*@param b - the quadword to be counted
*@returns the number of 1 bits in b
*/
#define m1 0x5555555555555555ULL
#define m2 0x3333333333333333ULL
unsigned popCount(bitboard b)
{
assert(UINT_MAX >= 0xffffffff);
unsigned n;
const bitboard a = b - ((b >1) & m1);
const bitboard c = (a & m2) + ((a >2) & m2);
n = (unsigned) ((c & 0xffffffff) + (c >32));
n = (n & 0x0F0F0F0F) + ((n >4) & 0x0F0F0F0F);
n = (n & 0xFFFF) + (n >16);
n = (n & 0xFF) + (n >8);
return n;
}
Jul 18 '06 #7
John wrote:
Trying to return the number of 'on' bits in a byte:
'a' = 01100001 = 3 on bits, etc...

I'm just adding a bit-wise AND ('&' against octal 1) to a counter called
'bits', then shifting my byte 1 bit to the right; do this 8 times.

This works, but I was curious if there's some more effective formula
without looping or recursion? That seems like an awful lot of code, but
I can't think of a better way.
int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
Don't worry about char, use unsigned int.

#include <stdio.h>
#include <stdlib.h>

int bits(unsigned u) {
int ret = 0;
if (u) ++ret;
while ((u &= u - 1)) ++ret;
return ret;
}

int main(int argc, char *argv[]) {
int ans;
unsigned try = 255;
if (argc 1) {
try = (unsigned)atoi(argv[1]);
}
ans = bits(try);
printf("%u has %d bit%s\n", try, ans, ans == 1 ? "" : "s");
return 0;
}

Enjoy..
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jul 19 '06 #8
John wrote:
Trying to return the number of 'on' bits in a byte:
'a' = 01100001 = 3 on bits, etc...

I'm just adding a bit-wise AND ('&' against octal 1) to a counter called
'bits', then shifting my byte 1 bit to the right; do this 8 times.

This works, but I was curious if there's some more effective formula
without looping or recursion? That seems like an awful lot of code, but
I can't think of a better way.
int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
For the perverse:

unsigned bitCount( unsigned char n )
{
unsigned count = 0;

if( n ) {
count = bitCount( n >1 );
}
return count+(n&1);
}

--
Ian Collins.
Jul 19 '06 #9
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Tom St Denis wrote:
1. Right shifting signed types == bad
Out of curiosity, why specifically do you say that?

Is it just because you don't necessairily know how many bits are in a
given type? (Mind you, with char it's a pretty safe assumption you've
got 8.)

- --
Regards,
Jonathan Lamothe

/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/

die_if_kernel("Oops", regs, error_code);
-- From linux/arch/i386/mm/fault.c
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEvZZ+q9nD47x87JYRAqOUAJwPC2ctBPW2lb47j3dMWr 2hKcJlLwCfctEC
e0t8HL6bG5S5c/9quZs6pTw=
=bCmW
-----END PGP SIGNATURE-----
Jul 19 '06 #10

Jonathan Lamothe wrote:
>
Tom St Denis wrote:
1. Right shifting signed types == bad

Out of curiosity, why specifically do you say that?
It's not portable. If the value being shifted is negative, the result
of the shift is implementation defined - it can be different on
different compilers and systems.
(Mind you, with char it's a pretty safe assumption you've got 8.)
That you've got at least 8, certainly.

Jul 19 '06 #11
Tom St Denis (in
11**********************@b28g2000cwb.googlegroups. com) said:

| Morris Dovey wrote:
|| int BitCount(unsigned char c)
|| { int bits = 0;
|| do bits += c & 1; while (c >>= 1);
|| return bits;
|| }
|
| bah
|
| int bitcount(unsigned char c)
| {
| unsigned char s;
| s = (c & 0x11);
| s += ((c >1) & 0x11);
| s += ((c >2) & 0x11);
| s += ((c >3) & 0x11);
| return (s&15) + (s>>4);
| }
|
| Compared to the other approach which requires on average 15 ANDs,
| shifts, additions and XORs this approach only requires 6 ANDs, 5
| shifts and 5 additions. It's also constant time (in the realtime
| sense).
|
| :-)

I'm intrigued by your analysis. How were you able to arrive at these
averages for my (admittedly crude) method of counting 'on' bits in an
unsigned char. I'm especially interested in how you arrived at the XOR
contribution. :-)

If you like that approach, why wouldn't you:

int BitCount(unsigned char c)
{ unsigned char s = c & 0111;
s += (c >1) & 0111;
s += (c >2) & 011;
return (s&3) + ((s>>3)&3) + (s>>6);
}

5 ANDs, 4 shifts, 4 additions (and, of course, constant time) :-D

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Jul 19 '06 #12

John wrote:
Trying to return the number of 'on' bits in a byte:
'a' = 01100001 = 3 on bits, etc...

I'm just adding a bit-wise AND ('&' against octal 1) to a counter called
'bits', then shifting my byte 1 bit to the right; do this 8 times.

This works, but I was curious if there's some more effective formula
without looping or recursion? That seems like an awful lot of code, but
I can't think of a better way.
int BitCount(char c)
{
int ctr;
int bits = 0;
for (ctr = 0; ctr < 8; ctr++) {
bits += c & 0001;
c >>= 1;
}
return (bits);
}
http://graphics.stanford.edu/~seande...tsSetKernighan

Jul 19 '06 #13

John wrote:
Trying to return the number of 'on' bits in a byte:
'a' = 01100001 = 3 on bits, etc...
<NON_PORTABLE GCC-SPECIFIC CODE>

printf("x has %d bits set\n", __builtin_popcount(x));

<\NON_PORTABLE GCC-SPECIFIC CODE>

Note that whatever architecture you're on may have
an assembly level command for returning the
number of bits set in a register. The lookup table
on 8 bits is, IMO a better solution.

Jul 19 '06 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Ken | last post by:
I need to convert 32 bit Windows bitmaps to jpgs with PHP. I used the function from http://groups.google.com/groups? hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=a164f4b5.0311302128.40fb37f4%...
10
by: Eric | last post by:
I have an array that contains over 30000+ bits. The size varies at runtime. I need to move through this chunk of memory and count bits every so often. Example: First 9 bits has 2 ones, next 10...
8
by: Sowen | last post by:
Hi, all I am wondering how to write bits by using ofstream? I have finished a huffman tree, but how can I write the bits to the file in order to gain compression? for example, 'A' returns a...
11
by: Hur | last post by:
hi i ask two questions......someone can tell me i an a linux gcc user and wanna know that - how much physical memory is used for my c code ? and another one is - i need a (standard)...
19
by: Ross A. Finlayson | last post by:
Hi, I hope you can help me understand the varargs facility. Say I am programming in ISO C including stdarg.h and I declare a function as so: void log_printf(const char* logfilename, const...
7
by: sathyashrayan | last post by:
Group, Following function will check weather a bit is set in the given variouble x. int bit_count(long x) { int n = 0; /* ** The loop will execute once for each bit of x set,
7
by: zets | last post by:
I need a macro for counting the bits in the odd positions of a given input (of any type, char, pointer, int, struct, whatever). Is there any clever way I could not think of, to do it efficiently? ...
77
by: borophyll | last post by:
As I read it, C99 states that a byte is an: "addressable unit of data storage large enough to hold any member of the basic character set of the execution environment" (3.6) and that a byte...
29
by: Virtual_X | last post by:
As in IEEE754 double consist of sign bit 11 bits for exponent 52 bits for fraction i write this code to print double parts as it explained in ieee754 i want to know if the code contain any...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.