Open In App

Program to count number of set bits in an (big) array

Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer array of length N (an arbitrarily large number). How to count number of set bits in the array?
The simple approach would be, create an efficient method to count set bits in a word (most prominent size, usually equal to bit length of processor), and add bits from individual elements of array.
Various methods of counting set bits of an integer exists, see this for example. These methods run at best O(logN) where N is number of bits. Note that on a processor N is fixed, count can be done in O(1) time on 32 bit machine irrespective of total set bits. Overall, the bits in array can be computed in O(n) time, where ‘n’ is array size.
However, a table look up will be more efficient method when array size is large. Storing table look up that can handle 232 integers will be impractical.
The following code illustrates simple program to count set bits in a randomly generated 64 K integer array. The idea is to generate a look up for first 256 numbers (one byte), and break every element of array at byte boundary. A meta program using C/C++ preprocessor generates the look up table for counting set bits in a byte.
The mathematical derivation behind meta program is evident from the following table (Add the column and row indices to get the number, then look into the table to get set bits in that number. For example, to get set bits in 10, it can be extracted from row named as 8 and column named as 2), 
 

   0, 1, 2, 3
 0 - 0, 1, 1, 2 -------- GROUP_A(0)
 4 - 1, 2, 2, 3 -------- GROUP_A(1)
 8 - 1, 2, 2, 3 -------- GROUP_A(1)
12 - 2, 3, 3, 4 -------- GROUP_A(2)
16 - 1, 2, 2, 3 -------- GROUP_A(1)
20 - 2, 3, 3, 4 -------- GROUP_A(2)
24 - 2, 3, 3, 4 -------- GROUP_A(2)
28 - 3, 4, 4, 5 -------- GROUP_A(3) ... so on

From the table, there is a pattern emerging in multiples of 4, both in the table as well as in the group parameter. The sequence can be generalized as shown in the code.
Complexity:
All the operations takes O(1) except iterating over the array. The time complexity is O(n) where ‘n’ is size of array. Space complexity depends on the meta program that generates look up.
Code: 
 

C++




#include <bits/stdc++.h>
#include <time.h>
using namespace std;
 
/* Size of array 64 K */
#define SIZE (1 << 16)
 
/* Meta program that generates set bit count
array of first 256 integers */
 
/* GROUP_A - When combined with META_LOOK_UP
generates count for 4x4 elements */
 
#define GROUP_A(x) x, x + 1, x + 1, x + 2
 
/* GROUP_B - When combined with META_LOOK_UP
generates count for 4x4x4 elements */
 
#define GROUP_B(x)                                         \
    GROUP_A(x), GROUP_A(x + 1), GROUP_A(x + 1),            \
        GROUP_A(x + 2)
 
/* GROUP_C - When combined with META_LOOK_UP
generates count for 4x4x4x4 elements */
 
#define GROUP_C(x)                                         \
    GROUP_B(x), GROUP_B(x + 1), GROUP_B(x + 1),            \
        GROUP_B(x + 2)
 
/* Provide appropriate letter to generate the table */
 
#define META_LOOK_UP(PARAMETER)                            \
    \
GROUP_##PARAMETER(0),                                      \
        \
GROUP_##PARAMETER(1),                                      \
        \
GROUP_##PARAMETER(1),                                      \
        \
GROUP_##PARAMETER(2)\
 
int countSetBits(int array[], size_t array_size)
{
    int count = 0;
 
    /* META_LOOK_UP(C) - generates a table of 256 integers
       whose sequence will be number of bits in i-th
       position where 0 <= i < 256
    */
 
    /* A static table will be much faster to access */
    static unsigned char const look_up[]
        = { META_LOOK_UP(C) };
 
    /* No shifting funds (for better readability) */
    unsigned char* pData = NULL;
 
    for (size_t index = 0; index < array_size; index++) {
        /* It is fine, bypass the type system */
        pData = (unsigned char*)&array[index];
 
        /* Count set bits in individual bytes */
        count += look_up[pData[0]];
        count += look_up[pData[1]];
        count += look_up[pData[2]];
        count += look_up[pData[3]];
    }
 
    return count;
}
 
/* Driver program, generates table of random 64 K numbers */
int main()
{
    int index;
    int random[SIZE];
 
    /* Seed to the random-number generator */
    srand((unsigned)time(0));
 
    /* Generate random numbers. */
    for (index = 0; index < SIZE; index++) {
        random[index] = rand();
    }
 
    cout << "Total number of bits = "
         << countSetBits(random, SIZE);
    return 0;
}
 
// This is code is contributed by rathbhupendra


C




#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
/* Size of array 64 K */
#define SIZE (1 << 16)
 
/* Meta program that generates set bit count
   array of first 256 integers */
 
/* GROUP_A - When combined with META_LOOK_UP
   generates count for 4x4 elements */
 
#define GROUP_A(x) x, x + 1, x + 1, x + 2
 
/* GROUP_B - When combined with META_LOOK_UP
   generates count for 4x4x4 elements */
 
#define GROUP_B(x)                                         \
    GROUP_A(x), GROUP_A(x + 1), GROUP_A(x + 1),            \
        GROUP_A(x + 2)
 
/* GROUP_C - When combined with META_LOOK_UP
   generates count for 4x4x4x4 elements */
 
#define GROUP_C(x)                                         \
    GROUP_B(x), GROUP_B(x + 1), GROUP_B(x + 1),            \
        GROUP_B(x + 2)
 
/* Provide appropriate letter to generate the table */
 
#define META_LOOK_UP(PARAMETER)                            \
    GROUP_##PARAMETER(0), GROUP_##PARAMETER(1),            \
        GROUP_##PARAMETER(1), GROUP_##PARAMETER(2)
 
int countSetBits(int array[], size_t array_size)
{
    int count = 0;
 
    /* META_LOOK_UP(C) - generates a table of 256 integers
       whose sequence will be number of bits in i-th
       position where 0 <= i < 256
    */
 
    /* A static table will be much faster to access */
    static unsigned char const look_up[]
        = { META_LOOK_UP(C) };
 
    /* No shifting funds (for better readability) */
    unsigned char* pData = NULL;
 
    for (size_t index = 0; index < array_size; index++) {
        /* It is fine, bypass the type system */
        pData = (unsigned char*)&array[index];
 
        /* Count set bits in individual bytes */
        count += look_up[pData[0]];
        count += look_up[pData[1]];
        count += look_up[pData[2]];
        count += look_up[pData[3]];
    }
 
    return count;
}
 
/* Driver program, generates table of random 64 K numbers */
int main()
{
    int index;
    int random[SIZE];
 
    /* Seed to the random-number generator */
    srand((unsigned)time(0));
 
    /* Generate random numbers. */
    for (index = 0; index < SIZE; index++) {
        random[index] = rand();
    }
 
    printf("Total number of bits = %d\n",
           countSetBits(random, SIZE));
    return 0;
}


Java




import java.util.*;
 
class Main {
 
    /* Size of array 64 K */
    private static final int SIZE = (1 << 16);
 
    /* Meta program that generates set bit count
    array of first 256 integers */
 
    /* GROUP_A - When combined with META_LOOK_UP
    generates count for 4x4 elements */
 
    private static int[] GROUP_A(int x)
    {
        return new int[] { x, x + 1, x + 1, x + 2 };
    }
 
    /* GROUP_B - When combined with META_LOOK_UP
    generates count for 4x4x4 elements */
 
    private static int[] GROUP_B(int x)
    {
        return new int[] {
            GROUP_A(x)[0],     GROUP_A(x)[1],
            GROUP_A(x)[2],     GROUP_A(x)[3],
            GROUP_A(x + 1)[0], GROUP_A(x + 1)[1],
            GROUP_A(x + 1)[2], GROUP_A(x + 1)[3],
            GROUP_A(x + 1)[0], GROUP_A(x + 1)[1],
            GROUP_A(x + 1)[2], GROUP_A(x + 1)[3],
            GROUP_A(x + 2)[0], GROUP_A(x + 2)[1],
            GROUP_A(x + 2)[2], GROUP_A(x + 2)[3],
        };
    }
 
    /* GROUP_C - When combined with META_LOOK_UP
    generates count for 4x4x4x4 elements */
 
    private static int[] GROUP_C(int x)
    {
        return new int[] {
            GROUP_B(x)[0],     GROUP_B(x)[1],
            GROUP_B(x)[2],     GROUP_B(x)[3],
            GROUP_B(x + 1)[0], GROUP_B(x + 1)[1],
            GROUP_B(x + 1)[2], GROUP_B(x + 1)[3],
            GROUP_B(x + 1)[0], GROUP_B(x + 1)[1],
            GROUP_B(x + 1)[2], GROUP_B(x + 1)[3],
            GROUP_B(x + 2)[0], GROUP_B(x + 2)[1],
            GROUP_B(x + 2)[2], GROUP_B(x + 2)[3],
        };
    }
 
    /* Provide appropriate letter to generate the table */
 
    public static int[] META_LOOK_UP(String parameter)
    {
        int[] look_up = new int[256];
        switch (parameter) {
        case "A":
            // When combined with META_LOOK_UP generates
            // count for 4x4 elements
            for (int i = 0; i < 256; i += 2) {
                int x = i + (i << 8);
                look_up[i] = look_up[i + 1] = GROUP_A(x)[0];
                look_up[i + 2] = look_up[i + 3]
                    = GROUP_A(x)[1];
            }
            break;
        case "B":
            // When combined with META_LOOK_UP generates
            // count for 4x4x4 elements
            for (int i = 0; i < 256; i += 4) {
                int x = i + (i << 8);
                int[] groupB = GROUP_B(x);
                look_up[i] = groupB[0];
                look_up[i + 1] = groupB[1];
                look_up[i + 2] = groupB[2];
                look_up[i + 3] = groupB[3];
            }
            break;
        case "C":
            // When combined with META_LOOK_UP generates
            // count for 4x4x4x4 elements
            for (int i = 0; i < 256; i += 16) {
                int x = i + (i << 8);
                int[] groupC = GROUP_C(x);
                for (int j = 0; j < 16; j++) {
                    look_up[i + j] = groupC[j];
                }
            }
            break;
        default:
            throw new IllegalArgumentException(
                "Invalid parameter: " + parameter);
        }
        return look_up;
    }
 
    public static int countSetBits(int[] array)
    {
        int count = 0;
 
        // META_LOOK_UP(C) - generates a table of 256
        // integers whose sequence will be number of bits in
        // i-th position where 0 <= i < 256 A static table
        // will be much faster to access
        int[] look_up = META_LOOK_UP("C");
 
        for (int index = 0; index < array.length; index++) {
            // Count set bits in individual bytes
            count += look_up[array[index] & 0xff];
            count += look_up[(array[index] >> 8) & 0xff];
            count += look_up[(array[index] >> 16) & 0xff];
            count += look_up[(array[index] >> 24) & 0xff];
        }
 
        return count;
    }
 
    public static void main(String[] args)
    {
        final int SIZE = (1 << 16);
        int[] random = new int[SIZE];
 
        // Generate random numbers.
        for (int i = 0; i < SIZE; i++) {
            random[i]
                = (int)(Math.random() * Math.pow(2, 32));
        }
 
        System.out.println("Total number of bits = "
                           + countSetBits(random));
    }
}


Python3




import random
import time
 
# Size of array 64 K
SIZE = 1 << 16
 
# Look-up table generation macros
 
 
def GROUP_A(x):
    return x, x + 1, x + 1, x + 2
 
 
def GROUP_B(x):
    return GROUP_A(x) + GROUP_A(x+1) + GROUP_A(x+1) + GROUP_A(x+2)
 
 
def GROUP_C(x):
    return GROUP_B(x) + GROUP_B(x+1) + GROUP_B(x+1) + GROUP_B(x+2)
 
 
def META_LOOK_UP(PARAMETER):
    return GROUP_C(PARAMETER)
 
# Count the number of set bits in an array of integers
 
 
def count_set_bits(array):
    count = 0
 
    # Look-up table for counting set bits in a byte
    look_up = bytearray(META_LOOK_UP(0) + META_LOOK_UP(1) +
                        META_LOOK_UP(1) + META_LOOK_UP(2))
 
    for value in array:
        # Count set bits in individual bytes
        count += look_up[value & 0xFF]
        count += look_up[(value >> 8) & 0xFF]
        count += look_up[(value >> 16) & 0xFF]
        count += look_up[(value >> 24) & 0xFF]
 
    return count
 
# Driver program, generates table of random 64 K numbers
 
 
def main():
    # Seed to the random-number generator
    random.seed(time.time())
 
    # Generate random numbers
    random_numbers = [random.randint(0, 2**32-1) for _ in range(SIZE)]
 
    print("Total number of bits =", count_set_bits(random_numbers))
 
 
if __name__ == '__main__':
    main()
 
# This is code is contributed by rutikbhosale


Javascript




/* Size of array 64 K */
const SIZE = (1 << 16);
 
/* Meta program that generates set bit count
array of first 256 integers */
 
/* GROUP_A - When combined with META_LOOK_UP
generates count for 4x4 elements */
 
const GROUP_A = (x) => [x, x + 1, x + 1, x + 2];
 
/* GROUP_B - When combined with META_LOOK_UP
generates count for 4x4x4 elements */
 
const GROUP_B = (x) => [
  ...GROUP_A(x),
  ...GROUP_A(x + 1),
  ...GROUP_A(x + 1),
  ...GROUP_A(x + 2)
];
 
/* GROUP_C - When combined with META_LOOK_UP
generates count for 4x4x4x4 elements */
 
const GROUP_C = (x) => [
  ...GROUP_B(x),
  ...GROUP_B(x + 1),
  ...GROUP_B(x + 1),
  ...GROUP_B(x + 2)
];
 
/* Provide appropriate letter to generate the table */
 
const META_LOOK_UP = (PARAMETER) => [
  ...GROUP_C(0),
  ...GROUP_C(1),
  ...GROUP_C(1),
  ...GROUP_C(2)
];
 
function countSetBits(array) {
  let count = 0;
 
  /* META_LOOK_UP(C) - generates a table of 256 integers whose
    sequence will be number of bits in i-th position
    where 0 <= i < 256
  */
 
  /* A static table will be much faster to access */
  const look_up = new Uint8Array(META_LOOK_UP("C"));
 
  for (let index = 0; index < array.length; index++) {
    /* Count set bits in individual bytes */
    count += look_up[array[index] & 0xff];
    count += look_up[(array[index] >> 8) & 0xff];
    count += look_up[(array[index] >> 16) & 0xff];
    count += look_up[(array[index] >> 24) & 0xff];
  }
 
  return count;
}
 
/* Driver program, generates table of random 64 K numbers */
function main() {
  const random = new Uint32Array(SIZE);
 
  /* Generate random numbers. */
  for (let index = 0; index < SIZE; index++) {
    random[index] = Math.floor(Math.random() * Math.pow(2, 32));
  }
 
  console.log("Total number of bits = " + countSetBits(random));
}
 
main();
// This is code is contributed by rutikbhosale


C#




using System;
 
namespace SetBitCount {
class Program {
    // Size of array 64 K
    const int SIZE = 1 << 16;
 
    // Meta program that generates set bit count
    // array of first 256 integers
    // GROUP_A - When combined with META_LOOK_UP generates
    // count for 4x4 elements
    const string GROUP_A = "{0}, {1}, {1}, {2}";
    // GROUP_B - When combined with META_LOOK_UP generates
    // count for 4x4x4 elements
    const string GROUP_B = GROUP_A + ", " + GROUP_A + ", "
                           + GROUP_A + ", " + GROUP_A;
    // GROUP_C - When combined with META_LOOK_UP generates
    // count for 4x4x4x4 elements
    const string GROUP_C = GROUP_B + ", " + GROUP_B + ", "
                           + GROUP_B + ", " + GROUP_B;
 
    // Provide appropriate letter to generate the table
    const string META_LOOK_UP = @" " + GROUP_C + @" ";
 
        static int
        CountSetBits(int[] array, int arraySize)
    {
        int count = 0;
 
        // META_LOOK_UP(C) - generates a table of 256
        // integers whose sequence will be number of bits in
        // i-th position where 0 <= i < 256 A static table
        // will be much faster to access
        byte[] lookUpTable
            = new byte[256] { " + META_LOOK_UP + @" };
 
        for (int i = 0; i < arraySize; i++) {
            // It is fine, bypass the type system
            byte[] pData = BitConverter.GetBytes(array[i]);
 
            // Count set bits in individual bytes
            count += lookUpTable[pData[0]];
            count += lookUpTable[pData[1]];
            count += lookUpTable[pData[2]];
            count += lookUpTable[pData[3]];
        }
 
        return count;
    }
 
    // Driver program, generates table of random 64 K
    // numbers
    static void Main(string[] args)
    {
        int[] random = new int[SIZE];
 
        // Seed to the random-number generator
        Random rand = new Random();
 
        // Generate random numbers.
        for (int i = 0; i < SIZE; i++) {
            random[i] = rand.Next();
        }
 
        Console.WriteLine("Total number of bits = "
                          + CountSetBits(random, SIZE));
    }
}
}


Time Complexity: O(n)

Auxiliary Space: O(size)

Contributed by Venki.
 



Last Updated : 17 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads