【发布时间】:2018-08-03 09:45:54
【问题描述】:
我知道有一些关于如何实现*的帖子,但我真的很难用我目前的筛子方法来实现一个。
我在 C 中创建了自己的位数组,实现如下:
#define setBit1(Array, i) (Array[i/INT_BITS] |= (1 << i % INT_BITS))
#define getBit(Array, i) ((Array[i/INT_BITS] & (1 << i % INT_BITS)) ? 1 : 0)
#define setBit0(Array, i) (Array[i/INT_BITS] &= ~(1 << i % INT_BITS))
int * createBitArray(unsigned long long size) {
// find bytes required, round down to nearest whole byte
unsigned long long bytesRequired = size / BITS_PERBYTE;
// round up to highest multiple of 4 or 8 bytes (one int)
bytesRequired = (sizeof(int) * (bytesRequired / sizeof(int) +
((size % BITS_PERBYTE * sizeof(int) == 0) ? 0 : 1)));
// allocate array of "bits", round number of ints required up
return (int *)malloc((bytesRequired));
}
我使用 clock() 在 C 语言中做了一些测试,我发现对于超过 1,000,000 的大数组大小,位数组,即使使用它的位操作,至少比它快 200%一个整数数组。它也使用了 1/32 的内存。
#define indexToNum(n) (2*n + 1)
#define numToIndex(n) ((n - 1) / 2)
typedef unsigned long long LONG;
// populates prime array through Sieve of Eratosthenes, taking custom
// odd keyed bit array, and the raw array length, as arguments
void findPrimes(int * primes, LONG arrLength) {
long sqrtArrLength = (long)((sqrt((2 * arrLength) + 1) - 1) / 2);
long maxMult = 0;
long integerFromIndex = 0;
for (int i = 1; i <= sqrtArrLength; i++) {
if (!getBit(primes, i)) {
integerFromIndex = indexToNum(i);
maxMult = (indexToNum(arrLength)) / integerFromIndex;
for (int j = integerFromIndex; j <= maxMult; j+= 2) {
setBit1(primes, numToIndex((integerFromIndex*j)));
}
}
}
}
我一直在用索引 i 填充位数组,该索引表示通过 (2i + 1) 获得的数字。这样做的好处是减少了迭代偶数所花费的任何时间,并再次将数组的必要内存减少了一半。 2 是手动添加到素数之后。这是由于在索引和数字之间转换所花费的时间,但在我的测试中,对于 1,000 多个素数,这种方法更快。
我不知道如何进一步优化;我减少了数组大小,我只测试 sqrt(n),我开始从 p * p 向上“筛选”素数,我已经消除了所有偶数,我仍然需要大约 60 秒C 中的前 100,000,000 个素数。
据我所知,“wheel”方法要求将数字的实际整数存储在索引中。我真的坚持用我当前的位数组来实现它。
【问题讨论】:
-
抱歉,*是什么?
-
Tomas Oliveira y Silva(我可能拼错了)写出了最快的筛子,并在http://sweet.ua.pt/tos/software/prime_sieve.html 上描述了它。
-
你需要在 malloc() 之后用零填充该数组
-
数组在 malloc 后隐式初始化为零。一个一个地打印所有位证实了这一点。这是意料之外的……?我正在使用 GCC C99。
标签: arrays algorithm optimization primes sieve-of-eratosthenes