eratosthenes的筛子:有点优化

时间:2013-07-17 14:16:03

标签: c++ algorithm sorting optimization refactoring

在网上搜索之后,我开始知道eratosthenes筛子的逐位版非常有效。 问题是我无法理解它正在使用的数学/方法。

我一直忙着的版本看起来像这样:

#define MAX 100000000
#define LIM 10000

unsigned flag[MAX>>6]={0};

#define ifc(n) (flag[n>>6]&(1<<((n>>1)&31)))         //LINE 1
#define isc(n) (flag[n>>6]|=(1<<((n>>1)&31)))        //LINE 2

void sieve() {
    unsigned i, j, k;
    for(i=3; i<LIM; i+=2)
        if(!ifc(i))
            for(j=i*i, k=i<<1; j<LIM*LIM; j+=k)
                isc(j);
}

我理解的要点(如果我错了请纠正我):

  1. 第1行中的陈述检查该号码是否为复合号。
  2. 第2行中的陈述将数字'n'标记为复合。
  3. 程序将值0或1存储在int的位。这往往会将内存使用量减少到x / 32。 (x是使用int来存储0或1而不是像我上面的解决方案中那样使用的大小)
  4. 截至目前为止已经超越我的头脑了:

    1. LINE 1中的结尾如何运作。如何确保数字是否是复合的。
    2. LINE 2中的功能如何设置位。
    3. 我也知道按位筛是时间效率的 好。是因为仅使用按位运算符还是 其他东西也有助于它。
    4. 有任何想法或建议吗?

1 个答案:

答案 0 :(得分:4)

从技术上讲,代码中也存在一个错误:

无符号标志[MAX&gt;&gt; 6] = {0};

MAX除以64,但如果MAX不是64的精确倍数,则数组是一个短元素。

第1行:让我们分开:

 (flag[n>>6]&(1<<((n>>1)&31)))

flag[n>>6] (n >> 6 = n / 64)给出了保存n / 2位值的32位整数。

由于只有“奇数”数字是可能的素数,因此将n除以2:(n>>1)

1<<((n>>1)&31)n/2中为0..31提供了与& 31相对应的位 - (&确保它在“范围内”)。

最后,使用n将左侧的值与右侧的值组合。

因此,如果n modulo 32的元素设置了位号|=,则结果为真。

第二行基本上是相同的概念,只是它使用{{1}}(或相等)来设置对应于倍数的位。