在网上搜索之后,我开始知道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);
}
我理解的要点(如果我错了请纠正我):
截至目前为止已经超越我的头脑了:
有任何想法或建议吗?
答案 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}}(或相等)来设置对应于倍数的位。