获取BitMap

时间:2017-02-19 07:30:51

标签: c bitmap bit-manipulation

在C中,是否有任何优化的方法来检索BitPositions列表而不解析每个位。

考虑以下示例

int bitmap[4];

因此,有4 * 32位位置。值等于

bitmap = { 0x1, 0x0, 0x0, 0x0010001 }

我希望检索每个位集的位置,而不是从0到4 * 32位置进行解析。

3 个答案:

答案 0 :(得分:0)

首先,人们不能真正在C中使用 int 作为位图,因为向左移位到符号位的行具有未定义的行为,C不保证表示是两个补码,或者int中有32位;据说避免这些陷阱的最简单方法是使用uint32_t来自<stdint.h>。因此

#include <stdint.h>
uint32_t bitmap[4];

因此,请考虑从索引0 ... 3中将这些位编号为0 ... 127;在索引0 ... 31之内;因此,您可以使用以下公式将索引转换为数组和该值中的位数:

int bit_number = // a value from 0 ... 127
int index = value >> 32; // shift right by number of bits in each index
int bit_in_value = value & 31; // take modulo 32 to get the bit in value

现在您可以通过以下方式索引整数:

bitmap[index];

并且所需值的位掩码为

uint32_t mask = (uint32_t)1 << bit_in_value;

因此您可以通过执行

来检查该位是否已设置
bit_is_set = !!(bitmap[index] & mask);

现在为了加快速度,您可以跳过index为0的任何bitmap[index],因为它不包含任何位;同样,在每个索引中,你可以通过将uint32_t中的位从位图移位1并用1屏蔽来加快速度。当uint32_t变为0时打破循环:

for (int index = 0; index <= 3; index ++) {
     uint32_t entry = bitmap[index];
     if (! entry) {
         continue;
     }

     int bit_number = 32 * index;
     while (entry) {
         if (entry & 1) {
             printf("bit number %d is set\n", bit_number);
         }
         entry >>= 1;
         bit_number ++;
     }   
}

除此之外,除了查找表或使用编译器内在函数(例如this to set which is the lowest bit set)之外没有太多加速,但你仍然必须使用一些。

答案 1 :(得分:0)

在O(k)中运行的最佳解决方案,其中k =整个列表中的设置位总数,可以通过使用查找表来实现。例如,您可以使用256个条目的表来描述该字节中每个设置位的位位置。索引将是字节的实际值。

对于每个条目,您可以使用以下结构。

struct
{
   int numberOfSetBits;
   char* list; // use malloc and alloocate the list according to numberOfSetBits
}

然后,您可以遍历每个结构的列表成员,迭代次数=该字节的设置位数。对于32位整数,您将不得不迭代这些结构中的4个,每个字节一个。要确定需要检查哪个条目,请使用位图并移位8位。注意,位位置是相对于该字节的,因此您可能必须添加一个偏移量或24,16或8,具体取决于您迭代的字节(假设为32位整数)。

注意:如果额外的内存使用对您来说不是问题,您可以构建一个64位的16位表项,并将结构数减少一半。

答案 2 :(得分:0)

关于这个问题,你可以看到What is the fastest way to return the positions of all set bits in a 64-bit integer?

一个简单的解决方案,但可能不是最快的,这取决于 log 和 pow 函数的时间:

#include<math.h>
#include<stdio.h>

void getSetBits(unsigned int num, int offset){

    int bit;
    while(num){
        bit = log2(num);
        num -= pow(2, bit);

        printf("%i\n", offset + bit); // use bit number
    }
}

int main(){
    int i, bitmap[4] = {0x1, 0x0, 0x0, 0x0010001};
    for(i = 0; i < 4; i++)
        getSetBits(bitmap[i], i * 32);
}

复杂度 O(D) | D 是设置位数。