主题:如何用筛法求素数?
XVenus
[专家分:20] 发布于 2005-06-19 15:07:00
请问如何用筛法求素数?
回复列表 (共25个回复)
沙发
liji [专家分:530] 发布于 2005-06-19 16:08:00
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);
}
板凳
不是归人 [专家分:1400] 发布于 2005-06-19 16:17:00
输出素数表,方法之一就是舍弃空间,换取时间,也就是用一个大数组来存放每一个数是不是素数。这样用筛法求素,大大的减少了时间。下面的筛法求素程序求(不输出,即不定义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 楼
XVenus [专家分:20] 发布于 2005-06-19 23:16:00
谢谢,不过我只会用TP呀
4 楼
不是归人 [专家分:1400] 发布于 2005-06-20 12:13:00
差不多,你把算法看懂了就行
主要是这
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 楼
hadewood [专家分:60] 发布于 2005-06-30 09:54:00
我觉得还是用素数分布的公式比较好
6 楼
rickone [专家分:15390] 发布于 2005-07-30 17:27:00
用筛法求素数表不用判断是否是素数,从假定开始(2)往后筛,为了减少筛的空间,可以先把偶数排除掉(2除外),虽然复杂度没变,还是有一点提高的。
7 楼
58132017 [专家分:50] 发布于 2005-07-31 17:51:00
我记得最简单的编素数的方法是
main()
{int i,j;
for(i=2;i<=100;i++)
for(j=2;i%j==0;j++)
}
8 楼
boxertony [专家分:23030] 发布于 2005-09-14 19:15:00
我见到的最快的筛选素数的程序是10亿内素数只需1秒(PIV 2.4g)。但它的源程序有几千行。
9 楼
iAkiak [专家分:8460] 发布于 2005-09-15 11:40:00
setcomposite与isprime运算量几乎一样,为什么不不把这个循环
while(m>=n)
{
if (isprime(m)) setcomposite((m*n));
m-=2;
}
直接写为
while(m>=n)
{
setcomposite(m*n);
m-=2;
}
呢?
10 楼
40404870 [专家分:160] 发布于 2005-10-03 16:49:00
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;
}
我来回复