回 帖 发 新 帖 刷新版面

主题:如何用筛法求素数?

请问如何用筛法求素数?

回复列表 (共25个回复)

沙发

int fun(int i)
{
if(i==2 || i==3 || i==5 || i==7) return 1;
if(i%2!=0 && i%3!=0 && i%5!=0 || i%7!=0) return 1;
}

main()
{
int i;
for(i=2;i<=100;i++)
if(fun(i)==1)
  printf("%d\n",i);
}

板凳

输出素数表,方法之一就是舍弃空间,换取时间,也就是用一个大数组来存放每一个数是不是素数。这样用筛法求素,大大的减少了时间。下面的筛法求素程序求(不输出,即不定义OUT)1亿以内的素数只需要十几秒的时间,远小于输出所需的时间。
    这个程序用一个char数组来存放每一个奇数是不是素数的信息。一个char是一个字节8位,存放8个数。
Program prime_char.cpp:
#include<iomanip>
#include<iostream>
#include<conio.h>
//#define DEBUG
#define OUT
using namespace std;
                //常量定义
const long MAX=100000000;
const long CHAR_MAX=int(MAX/16+1);
const char byt[8]={128,64,32,16,8,4,2,1};
                // 变量定义
/**********************************
prime saves whether n is a prime
the value of n is like:
prime[0]: 3, 5, 7, 9,11,13,15,17
prime[1]:19,21,23,25,27,29,31,33
**********************************/
unsigned char prime[CHAR_MAX];
                // 函数声明
inline bool isprime(long);
inline void setcomposite(long);
void primeinitiate(void);
void out(long);
                //函数定义
/****************************************
*Function main                          *
****************************************/
int main()
{
#ifdef DEBUG
  test();
#else
  long n,m;
  primeinitiate();
  n=5;
  while(n*n<=MAX)
  {
    if (isprime(n))
    {
#ifdef OUT
      out(n);
#endif
      m=int(MAX/n);
      if (m%2==0) m--;
      while(m>=n)
      {
        if (isprime(m)) setcomposite((m*n));
        m-=2;
      }
    }
  n+=2;
  }
#ifdef OUT
  for (;n<=MAX;n+=2)
  {
    if (isprime(n))
      out(n);
  }
#endif
#endif
  cout << "OK";
  getch();
  return 0;
}
/****************************************
*Test function                          *
****************************************/
void test(void)
{
}
/****************************************
*Function primeinitiate                 *
*to initiate the array prime[]          *
*input  : nothing                       *
*output : nothing                       *
****************************************/
void primeinitiate(void)
{
  long i;
  for(i=0;i<CHAR_MAX;i++)
  {
  if (i==0) prime[i]=237;       //11101101
  else if(i%3==0) prime[i]=109; //01101101
  else if(i%3==1) prime[i]=182; //10110110
  else if(i%3==2) prime[i]=219; //11011011
  }
}
/****************************************
*Function isprime                       *
*To know if we haven't been sure that   *
* n is a composite                      *
*Input  : n                             *
*Output : false if we are sure that n   *
*               is a composite;         *
*         ture  if we aren't sure that n*
*               is a composite;         *
****************************************/
inline bool isprime(long n)
{
  return ((prime[int((n-3)/16)] & byt[((n-3)%16)/2]) != 0);
}
/****************************************
*Function setcomposite                  *
*To let us be sure that an integer is   *
*a prime                                *
*Input  : n                             *
*Output : nothing                       *
****************************************/
inline void setcomposite(long n)
{
  prime[int((n-3)/16)] &= ~byt[((n-3)%16)/2];
//  return UNCHECKED;
}
void out(long n)
{
  static long i=0;
  cout << setw(5) << setiosflags(ios::right)<< n << " ";
  i++;
  i%=100;
  if (i%10==0) cout << endl;
  if (i%100==0) getch();
}
(以上程序经过Dev-C++ 4.9.6.0编译通过)

很久以前编的程序,现在拿出来见见天日吧。

3 楼

谢谢,不过我只会用TP呀

4 楼

差不多,你把算法看懂了就行
主要是这
while(n*n<=MAX)
  {
    if (isprime(n))
    {
      out(n);
      m=int(MAX/n);
      if (m%2==0) m--;
      while(m>=n)
      {
        if (isprime(m)) setcomposite((m*n));
        m-=2;
      }
    }
  n+=2;
  }
如果n是质数,那么n乘以所有大于n的不含有小于n的因子的数都是还没有被置为合数的合数。
这是我觉得一种比较高效的方法,楼主也可以写一个简单的,意思差不多。
另外学学读不同语言的程序很简单,但是非常有用。

5 楼

我觉得还是用素数分布的公式比较好

6 楼

用筛法求素数表不用判断是否是素数,从假定开始(2)往后筛,为了减少筛的空间,可以先把偶数排除掉(2除外),虽然复杂度没变,还是有一点提高的。

7 楼

我记得最简单的编素数的方法是
main()
{int i,j;
for(i=2;i<=100;i++)
for(j=2;i%j==0;j++)
}

8 楼

我见到的最快的筛选素数的程序是10亿内素数只需1秒(PIV 2.4g)。但它的源程序有几千行。

9 楼

setcomposite与isprime运算量几乎一样,为什么不不把这个循环
while(m>=n)
{
    if (isprime(m)) setcomposite((m*n));
    m-=2;
}
直接写为
while(m>=n)
{
    setcomposite(m*n);
    m-=2;
}
呢?

10 楼

while(n*n<=MAX)
  {
    if (isprime(n))
    {
      out(n);
      m=int(MAX/n);
      if (m%2==0) m--;
      while(m>=n)
      {
        if (isprime(m)) setcomposite((m*n));
        m-=2;
      }
    }
  n+=2;
  }

我来回复

您尚未登录,请登录后再回复。点此登录或注册