【发布时间】:2015-01-08 22:15:28
【问题描述】:
我正在寻找一种在内存消耗方面高效的素筛实现。
当然,素数测试本身应该以恒定的和最少数量的操作执行。
我已经实现了一个筛子,它只对与 6 的倍数相邻的数字表示素数。
对于任何其他数,要么是 2 或 3(因此是质数),要么是 2 或 3 的倍数(因此不是质数)。
所以这就是我想出的,我一直想知道在这些要求下是否有更好的东西:
界面:
#include <limits.h>
// Defined by the user (must be less than 'UINT_MAX')
#define RANGE 4000000000
// The actual length required for the prime-sieve array
#define ARR_LEN (((RANGE-1)/(3*CHAR_BIT)+1))
// Assumes that all entries in 'sieve' are initialized to zero
void Init(char sieve[ARR_LEN]);
// Assumes that 'Init(sieve)' has been called and that '1 < n < RANGE'
int IsPrime(char sieve[ARR_LEN],unsigned int n);
#if RANGE >= UINT_MAX
#error RANGE exceeds the limit
#endif
实施:
#include <math.h>
#define GET_BIT(sieve,n) ((sieve[(n)/(3*CHAR_BIT)]>>((n)%(3*CHAR_BIT)/3))&1)
#define SET_BIT(sieve,n) sieve[(n)/(3*CHAR_BIT)] |= 1<<((n)%(3*CHAR_BIT)/3)
static void InitOne(char sieve[ARR_LEN],int d)
{
unsigned int i,j;
unsigned int root = (unsigned int)sqrt((double)RANGE);
for (i=6+d; i<=root; i+=6)
{
if (GET_BIT(sieve,i) == 0)
{
for (j=6*i; j<RANGE; j+=6*i)
{
SET_BIT(sieve,j-i);
SET_BIT(sieve,j+i);
}
}
}
}
void Init(char sieve[ARR_LEN])
{
InitOne(sieve,-1);
InitOne(sieve,+1);
}
int IsPrime(char sieve[ARR_LEN],unsigned int n)
{
return n == 2 || n == 3 || (n%2 != 0 && n%3 != 0 && GET_BIT(sieve,n) == 0);
}
【问题讨论】:
-
这个问题似乎跑题了,因为它没有具体的编程问题。
-
有代表的人。 17,000 人应该真正认识到 StackOverflow 是关于具有特定答案的特定编程问题。诸如“有什么更好的”之类的问题不适合这里的问答格式。
-
@abelenky:是的,我在第一条评论中明白了你的意思,但我要求的是针对内存优化的素筛。如果我没有表现出任何努力,那么......好吧,你知道我会得到什么样的cmets。所以我分享了我的想法,现在我要求改进。它可以是一个算法解决方案,OR - 如果有人在我的实现中发现了一些明显的东西,那么它也可以是改进的建议。无论哪种情况,无论您的声誉如何,编程问题都应该非常清楚(请原谅我没有检查它)。
-
我相信你对CodeReview很熟悉。第一个“评论”不是故意评论。这只是投票结束的副作用。
-
@barakmanos 宏使用
[n / (3*CHAR_BIT)]索引数组,但数组大小声明为RANGE/3。不应该是RANGE/24吗?
标签: c optimization primes