C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Tip: This method always has accurate results, but it performs the fastest when most bits are set to zero.
Info: The effects of the binary operators are not part of this article, but they set, remove and shift bits.
Important: Bitwise operators cannot be used in place of boolean operators, and the reverse is also true.
C# program that counts bits with sparse method
using System;
class Program
{
static void Main()
{
Console.WriteLine( SparseBitcount(0));
Console.WriteLine( SparseBitcount(1));
Console.WriteLine( SparseBitcount(int.MaxValue));
Console.WriteLine( SparseBitcount(256));
}
static int SparseBitcount(int n)
{
int count = 0;
while (n != 0)
{
count++;
n &= (n - 1);
}
return count;
}
}
Output
0
1
31
1
C# program that uses iterated bit count
using System;
class Program
{
static void Main()
{
Console.WriteLine( IteratedBitcount(0));
Console.WriteLine( IteratedBitcount(1));
Console.WriteLine( IteratedBitcount(int.MaxValue));
Console.WriteLine( IteratedBitcount(256));
}
static int IteratedBitcount(int n)
{
int test = n;
int count = 0;
while (test != 0)
{
if ((test & 1) == 1)
{
count++;
}
test >>= 1;
}
return count;
}
}
Output
0
1
31
1
Note: You can instead use another bit counting mechanism to initialize each element in the table.
InitializeBitcounts: This populates each index with its bitcount. We use an efficient loop mechanism to initialize the bit counts.
ForC# program that uses precomputed bit counts
using System;
class Program
{
static void Main()
{
//
// Initialize the lookup table.
//
InitializeBitcounts();
//
// Get the bitcounts for these values by lookups.
//
Console.WriteLine( PrecomputedBitcount(0));
Console.WriteLine( PrecomputedBitcount(1));
Console.WriteLine( PrecomputedBitcount(int.MaxValue));
Console.WriteLine( PrecomputedBitcount(256));
}
static int[] _bitcounts; // Lookup table
static void InitializeBitcounts()
{
_bitcounts = new int[65536];
int position1 = -1;
int position2 = -1;
//
// Loop through all the elements and assign them.
//
for (int i = 1; i < 65536; i++, position1++)
{
//
// Adjust the positions we read from.
//
if (position1 == position2)
{
position1 = 0;
position2 = i;
}
_bitcounts[i] = _bitcounts[position1] + 1;
}
}
static int PrecomputedBitcount(int value)
{
//
// Count bits in each half of the 32-bit input number.
//
return _bitcounts[value & 65535] + _bitcounts[(value >> 16) & 65535];
}
}
Output
0
1
31
1
Version 1: This version of the code uses the sparse bit count method. Internally each iteration uses a loop.
Version 2: Here we use the iterated bit count method. This version appears to be the slowest by far.
Version 3: The precomputed version uses a lookup table, and this is not counted in the benchmark here.
Result: For runtime speed, it is best to use the precomputed bitcount. There is a start up and memory cost here.
C# program that benchmarks bit counts
using System;
using System.Diagnostics;
class Program
{
static void Main()
{
InitializeBitcounts();
const int m = 100000000;
Stopwatch s1 = Stopwatch.StartNew();
// Version 1: use sparse.
for (int i = 0; i < m; i++)
{
SparseBitcount(i);
}
s1.Stop();
Stopwatch s2 = Stopwatch.StartNew();
// Version 2: use iterated.
for (int i = 0; i < m; i++)
{
IteratedBitcount(i);
}
s2.Stop();
Stopwatch s3 = Stopwatch.StartNew();
// Version 3: use precomputed.
for (int i = 0; i < m; i++)
{
PrecomputedBitcount(i);
}
s3.Stop();
Console.WriteLine("{0}\n{1}\n{2}", s1.ElapsedMilliseconds, s2.ElapsedMilliseconds, s3.ElapsedMilliseconds);
}
static int SparseBitcount(int n)
{
int count = 0;
while (n != 0)
{
count++;
n &= (n - 1);
}
return count;
}
static int IteratedBitcount(int n)
{
int test = n;
int count = 0;
while (test != 0)
{
if ((test & 1) == 1)
{
count++;
}
test >>= 1;
}
return count;
}
static int[] _bitcounts;
static void InitializeBitcounts()
{
_bitcounts = new int[65536];
int position1 = -1;
int position2 = -1;
for (int i = 1; i < 65536; i++, position1++)
{
if (position1 == position2)
{
position1 = 0;
position2 = i;
}
_bitcounts[i] = _bitcounts[position1] + 1;
}
}
static int PrecomputedBitcount(int value)
{
return _bitcounts[value & 65535] + _bitcounts[(value >> 16) & 65535];
}
}
Output
704 ms Sparse bit count
5198 ms Iterated bit count
199 ms Precomputed bit count
Contribution: The bitcount initialization function shown here was contributed. Topher Cooper provided this algorithm.
Note: The previous method of using another bit computation on each element in the lookup table was almost ten times slower in my tests.