我需要帮助理解位图/位数组和按位运算。我理解二进制的基础知识以及左/右移位的工作方式,但我不确切知道这种用法是如何有益的。
基本上,我需要实现一个位图来存储一个主筛的结果(Eratosthenes。)这是一个较大的任务的一小部分,专注于不同的IPC方法,但要达到那个部分我需要得到筛子先完成。我从来没有使用过按位操作,也没有学过位图,所以我自己有点学习这个。
据我所知,位图是一个特定大小的数组,对吧?我的意思是你可以有一个8位数组或一个32位数组(在我的例子中,我需要找到一个32位无符号整数的素数,所以我需要32位数组。)所以如果这是一个位数组,其中32个是特定的,那么我们基本上是在讨论32个1和0的字符串。这如何转化为素数列表?我想一个方法会评估二进制数并将其保存为一个新的数组作为十进制,所以所有的十进制素数存在于一个数组中,但这似乎是你使用了太多的数据。
我是否掌握了位图的要点?还是有什么我想念的?我试过在互联网上阅读这个,但我找不到一个足以让我清楚的来源......
答案 0 :(得分:2)
假设您有一个素数列表:{3,5,7}。您可以将这些数字存储为字符数组:char c[] = {3, 5, 7}
,这需要3个字节。
而是让我们使用单个字节,使每个设置位指示该数字在集合中。例如,01010100。如果我们可以设置我们想要的字节并稍后测试它,我们可以使用它来在一个字节中存储相同的信息。设置它:
char b = 0;
// want to set `3` so shift 1 twice to the left
b = b | (1 << 2);
// also set `5`
b = b | (1 << 4);
// and 7
b = b | (1 << 6);
并测试这些数字:
// is 3 in the map:
if (b & (1 << 2)) {
// it is in...
答案 1 :(得分:1)
位图允许您在您感兴趣的数字范围内构建一个大的谓词函数。如果您只有一个8位字符,则可以为每个字符存储布尔值八个价值观。如果你有2个字符,它会使你的范围加倍。
因此,假设您有一个已存储此信息的位图,您的 test 函数可能如下所示:
bool num_in_bitmap (int num, char *bitmap, size_t sz) {
if (num/8 >= sz) return 0;
return (bitmap[num/8] >> (num%8)) & 1;
}
答案 2 :(得分:1)
您将需要超过32位。
你想要一个最多2 ^ 32个数字的筛子,所以你需要每个筛子一点。每个位代表一个数字,如果数字是素数则为0,如果是复数则为1。 (您可以通过注意第一位必须为2来保存一位,因为1既不是素数也不是复合。更容易浪费那一位。)
2 ^ 32 = 4,294,967,296
除以8
536,870,912字节,或1/2 GB。
所以你需要一个2 ^ 29字节,或2 ^ 27个4字节字的数组,或者你认为最好的数组,以及一个操作存储在数组中的字符(ints)中的各个位的方法
听起来最终,您将在此共享内存上运行多个线程或进程。如果您无法将所有内存分配给自己,则可能需要将其全部存储在文件中。
假设你想找到x的位。然后设a = x / 8且b = x - 8 * a。那个位在arr [a]&amp; (1 <&lt; b)。 (尽可能避免使用模数运算符%。)
//mark composite
a = x / 8;
b = x - 8 * a;
arr[a] |= 1 << b;
这听起来像一个有趣的任务!