判断一个整数是否为素数.(C语言)

rori 2003-04-29 11:02:15

判断一个整数是否为素数.
我总是感觉我写的程序有毛病,大家帮看看,是不是有毛病,谢谢。
prime/prime.c

#include <stdio.h>
int num;
int pri;
int prime (int);

int main()
{
printf ("Enter a number:");
scanf ("%d", &num);

pri=prime(num);

if (pri==0)
printf ("The number is not a prime.\n");
if (pri==1)
printf ("The number is a prime.\n");
}

int prime (int n)
{
int i;
for (i=2; i<n; i++) {
if (n%i == 0)
return 0;
else
return 1;
}
}

大家帮忙写个比较好的判断一个数是否是为素数的程序,谢谢。
...全文
15035 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
#include"math.h"
main()
{
int m,i,k;
scanf("%d",&m);
k=sqrt(m);
for(i=2;i<=k;i++)
if(m%i==0)break;
if(i>=k+1)printf("%d is a prime number\n",m);
else printf("%d is not a prime number\n",m);
}
libiyan 2003-04-29
  • 打赏
  • 举报
回复
: zzgcxy(傻小子) 这个的很好!!
int prime (int n)
{
int i;
for (i=2; i<n; i++) {
if (n%i == 0)
return 0;
}
return 1;
zzgcxy 2003-04-29
  • 打赏
  • 举报
回复
对验证到该数的平方根就行了。
zzgcxy 2003-04-29
  • 打赏
  • 举报
回复
int prime (int n)
{
int i;
for (i=2; i<n; i++) {
if (n%i == 0)
return 0;
}
return 1;

}
这样才是正确的,如果for执行到最后,则表示该数是素数,返回1。ok?
lbaby 2003-04-29
  • 打赏
  • 举报
回复
晕~~~

http://bbs.tencent.com/cgi-bin/bbs/bbs_show_content?from=t&groupid=102:10047&messageid=159242&club=3
zw741027 2003-04-29
  • 打赏
  • 举报
回复
不需要验证到n,验证到n的平方根即可
ninesong 2003-04-29
  • 打赏
  • 举报
回复
一个数num,
首先,除去2它不能是偶数。
如果num是素数那么它不会被2~sqrt(num)之间所有的素数整除,


for (int flag=0,i=3;i<sqrt(num);i+=2)
if(0==num%i) {
flag=1;break;
}

if (flag) 是素数,

这个只能判断比较小的素数。
xinghai09 2003-04-29
  • 打赏
  • 举报
回复
int prime (int n)
{
int i;
for (i=2; i<n; i++)
if (n%i == 0)
{
i=0;
break;
}
return i;
}
是素数返回正数,非素数返回 0
arfi 2003-04-29
  • 打赏
  • 举报
回复
你这个循环岂不没有了意义,执行一步就return掉了。
int prime (int n)
{
int i;
for (i=2; i<n; i++)
if (n%i == 0)
return 0;

return 1;
}
这样就行了。
rori 2003-04-29
  • 打赏
  • 举报
回复
嘿嘿,看来都是高手哦~一个素数问题居然有这么多学问,谢谢大家
lbaby 2003-04-29
  • 打赏
  • 举报
回复

各位见笑
wyqiang 2003-04-29
  • 打赏
  • 举报
回复
取一次平方根
有时乃花时太大
我想p/2就行
NowCan 2003-04-29
  • 打赏
  • 举报
回复
呵呵,看过这个。
你再看看这个。
http://expert.csdn.net/Expert/TopicView1.asp?id=1614558
100亿大约300秒。
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
我们可以定义一个结构如下,由它组成的数组作为素数表:
struct
{
int PrimeNum;
int Count;
};
初始化:
设置一个扫描变量n,从5开始扫,增量为2
素数表中开始只有3,其Count为0
扫描过程:
1、扫描素数表,把每一个成员的Count增加2,如果大于或等于PrimeNum,则减去PrimeNum(相当于求余);(相比用Count=(Count+2)%PrimeNum计算那个好我没有详细推敲,感觉上这个会好些,不知道谁能替我试试?)
2、当某一个Count经过步骤1后等于0,说明n能被整除,否则n为一个新素数,加入素数表,相应的Count设为0;
3、n增加2,执行步骤1。

分析上面的算法可见,整个算法中只有长整型数的加减!但有一个问题,不知道大家注意到没有,100亿以内有448848943个素数,建立这么一个素数表要用多少空间?一个天文数字!!解决方法很简单:判断100亿以内的数只需要看小于10万的素数就可以了,而10万以内的素数只有9592个,也就是说要用到的素数表长度只需9592就行了,总大小只有77K!

写到这里,我粗略算了一下,我这个算法平均每个数大约要算20000次加减法;而原来的算法一共要算484亿次乘法,再加上查表时间、数据交换时间,用时应该还是比我的短。
但我这个算法的优点是需要内存非常少,适合在更大范围(比如说1E11以内,这对于原算法就不可能了)内寻找。

呵呵,终于写完了!

也许有人会问大于10万的素数怎么办,很简单,直接输出就行了。 :)

阿崔[30656978] 2002-09-17 20:20
题目:Re:Re:Re:有关100亿内素数计算的算法与实现
( 瓜瓜牛[24470363]在大作中提到:)
> ……
> 但我这个算法的优点是需要内存非常少,更适合在非常大范围(比如说1E100以内)内寻找。
……
1E100?
开个根号应该是1E50吧?
1G=1E9
……还用我说什么吗?
这种算法只对十几位的小素数有效。
现在的大素数判别法(比如RSA里用的)都是以一定概率完成的。
不过找出一定范围内的素数,好像还是筛选法更有效。

瓜瓜牛[24470363] 2002-09-17 22:40
题目:Re:Re:Re:Re:有关100亿内素数计算的算法与
(阿崔[30656978]在大作中提到:)
> 1E100?
> 开个根号应该是1E50吧?
> 1G=1E9
> ……还用我说什么吗?
> 这种算法只对十几位的小素数有效。
> 现在的大素数判别法(比如RSA里用的)都是以一定概率完成的。
> 不过找出一定范围内的素数,好像还是筛选法更有效。

呵呵,我这也就是随口举个例子,你就别太较真了。

不过,谢谢你指出我的这个大话
我已经改过来了

阿崔[30656978] 2002-09-17 23:01
题目:Re:Re:Re:Re:Re:有关100亿内素数计算的算法
( 瓜瓜牛[24470363]在大作中提到:)
> 呵呵,我这也就是随口举个例子,你就别太较真了。
:)
偶的坏毛病

永不停息[11750919] 2002-09-18 09:11
题目:Re:Re:Re:有关100亿内素数计算的算法与实现
( 瓜瓜牛[24470363]在大作中提到:)
> 对于这个问题,不仅仅涉及到数据容量,更要仔细设计算法以提高计算速度。
> 原帖作者提出了一个相当好的方法,充分利用了奇数乘法末位数的自闭性,很精巧的完成了这个题目。
> 我仔细分析了他的算法,觉得有几个地方不是很完美:
> 1、在计算过程中要用到大量乘法,有没有办法避免呢?
> 2、虽然作者设计了数据压缩方法,把数据量压缩到了原来的5%,但仍然有几百兆,还能进一步提高吗?
>
> 针对这两个问题,我下面提出一种算法,没时间经过编程测试,不敢说比原来的好,就算是提出来让大家讨论讨论,希望能起到抛砖引玉的效果
>
> 这个算法脱胎于寻找素数的“筛法”,
> 首先我们知道2是唯一一个偶素数,所有其它偶数都不是素数,那么我们检查时就可以只看奇数。
> 在筛法中,先选最小的一个数,它必定是素数,然后去掉所有它的倍数,剩下的数中最小的那个是下一个素数,如此反复。直到最后没有去掉的数就是素数表。
> 另一个方面,如果我们一个数一个数扫描过去,看看比它小的素数中有没有它的因数,如果有,则为合数,否则就可以加入素数表。
> 我们可以比较一下这两种方法,为什么通常不用第二种呢?很显然这是因为第二种方法要比第一个多算很多除法。但第一个也有一个致命弱点:空间占用过大,不适合大范围寻找。
> 仔细考虑这些原因,可见第一个方法改进空间不大,做得再好也不会有根本上的改善;对于第二种方法,就要想办法减少甚至避免除法。
>
> 我们可以定义一个结构如下,由它组成的数组作为素数表:
> struct
> {
> int PrimeNum;
> int Count;
> };
> 初始化:
> 设置一个扫描变量n,从5开始扫,增量为2
> 素数表中开始只有3,其Count为0
> 扫描过程:
> 1、扫描素数表,把每一个成员的Count增加2,如果大于或等于PrimeNum,则减去PrimeNum(相当于求余);(相比用Count=(Count+2)%PrimeNum计算那个好我没有详细推敲,感觉上这个会好些,不知道谁能替我试试?)
> 2、当某一个Count经过步骤1后等于0,说明n能被整除,否则n为一个新素数,加入素数表,相应的Count设为0;
> 3、n增加2,执行步骤1。
>
> 分析上面的算法可见,整个算法中只有长整型数的加减!但有一个问题,不知道大家注意到没有,100亿以内有448848943个素数,建立这么一个素数表要用多少空间?一个天文数字!!解决方法很简单:判断100亿以内的数只需要看小于10万的素数就可以了,而10万以内的素数只有9592个,也就是说要用到的素数表长度只需9592就行了,总大小只有77K!
>
> 写到这里,我粗略算了一下,我这个算法平均每个数大约要算20000次加减法;而原来的算法一共要算484亿次乘法,再加上查表时间、数据交换时间,用时应该还是比我的短。
> 但我这个算法的优点是需要内存非常少,适合在更大范围(比如说1E11以内,这对于原算法就不可能了)内寻找。
>
> 呵呵,终于写完了!
>
> 也许有人会问大于10万的素数怎么办,很简单,直接输出就行了。 :)

非常精彩
我下去再想想这种实现方法
呵呵。

我这么长时间没有白花

^_^
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
疯猫[7825210] 2002-09-16 20:00
题目:Re:有关100亿内素数计算的算法与实现
对于这种大数据处理的问题
我认为关键是解决数据容量的问题

象在10的10次方中求素数这种问题
如果先不管方法的话 拿来就做的话

现在普通的40G的硬盘好象还不够定义的哦
呵呵

所以,对于这样的问题
可以将数组定义成一个 “位” 为单位的10的10次方的数组

然后将该字节全置为 1 用于标志是否素数

关于算法嘛

我现在只知道一个笨办法

那就是先求出一个 n*n<10000000000 的 最大的 n

然后从2开始循环到 n
将凡是该数的倍数的
则在前面的数组中的相应下标的 位 置成 1

最后只需要统计数组中有几个位还是 1 ,就大功告成了

不过
在计算的时候,不要以为自己的电脑死机哦 呵呵

瓜瓜牛[24470363] 2002-09-17 19:39
题目:Re:Re:有关100亿内素数计算的算法与实现
对于这个问题,不仅仅涉及到数据容量,更要仔细设计算法以提高计算速度。
原帖作者提出了一个相当好的方法,充分利用了奇数乘法末位数的自闭性,很精巧的完成了这个题目。
我仔细分析了他的算法,觉得有几个地方不是很完美:
1、在计算过程中要用到大量乘法,有没有办法避免呢?
2、虽然作者设计了数据压缩方法,把数据量压缩到了原来的5%,但仍然有几百兆,还能进一步提高吗?

针对这两个问题,我下面提出一种算法,没时间经过编程测试,不敢说比原来的好,就算是提出来让大家讨论讨论,希望能起到抛砖引玉的效果

这个算法脱胎于寻找素数的“筛法”,
首先我们知道2是唯一一个偶素数,所有其它偶数都不是素数,那么我们检查时就可以只看奇数。
在筛法中,先选最小的一个数,它必定是素数,然后去掉所有它的倍数,剩下的数中最小的那个是下一个素数,如此反复。直到最后没有去掉的数就是素数表。
另一个方面,如果我们一个数一个数扫描过去,看看比它小的素数中有没有它的因数,如果有,则为合数,否则就可以加入素数表。
我们可以比较一下这两种方法,为什么通常不用第二种呢?很显然这是因为第二种方法要比第一个多算很多除法。但第一个也有一个致命弱点:空间占用过大,不适合大范围寻找。
仔细考虑这些原因,可见第一个方法改进空间不大,做得再好也不会有根本上的改善;对于第二种方法,就要想办法减少甚至避免除法。
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
//begin of Primedat.h
#include<iostream.h>
#include<stdlib.h>
class Primedat
{
public:
int onedat; // one of the data
Primedat(int maxprime);
~Primedat();
void initdat(void); //设置指针位置
void marknonprime(void); //标记当前指针所指数据为非素数
void showprime(void); //显示当前指针所指数据
private:
int arrsize; //win98 一个内存页4kB
unsigned short **data; //指针数组,记录各数据数组的首地址
int arrnumlimit; //一个数组所能标记的素数上限
int datID; //内存块索引
int arrID; //数组中数据索引
int bitblockID; //数据内位块索引
int bitID; //位块内的位索引
int pointercunt; //实际申请到的指针数组长度 释放内存标记
int datacunt; //实际申请到的数组个数释放内存标记
short scrwd; //输出数据占屏幕宽度
unsigned short andortable[16];//标记各个数据位的数据表
unsigned short tmp; //取出的数据缓存
short allocerr; //内存分配错误次数
} ; //原来的时候,这里少了个';'所以出错
//end of Primedat.h

//Begin of Primedat.cpp
#include"Primedat.h"
#include<iostream.h>
Primedat::Primedat(int maxprime)
{
allocerr=0;
arrsize=4096; //win98一个内存页4kb,减少内存碎片
arrnumlimit=arrsize*40;
int i=0;
for(i=0;i<16;i++)
{
andortable[i]=1<<i;//此数据表用来屏蔽某些位或将某些位置1
}
int k=0;
int arrnum;
arrnum=maxprime/arrnumlimit+( ((maxprime%arrnumlimit)==0) ? 0 : 1);
cout<<"arrnum: "<<arrnum<<endl;
data=new unsigned short *[arrnum];//建立一个指针数组
if(data==NULL)
{
cout<<"存放指针的模块内存分配错误,程序不能完成指定的操作,任务被放弃"<<endl;
exit(1);
}
pointercunt=arrnum;
getmem:
try
{
for(;datacunt<arrnum;datacunt++)
{
*(data+datacunt)=new unsigned short[arrsize];
if( (*(data+datacunt)) == NULL)
{
throw datacunt;
}
}
}
catch(int datacunt) // 处理内存分配错误
{
allocerr++;
if(allocerr<3)
{
cout<<"在分配第"<<datacunt+1<<"块内存时失败,系统正在尝试重新分配"<<endl;
goto getmem;
}
else
{
cout<<"内存分配错误已达4次,可能操作系统内存不足。"<<endl
<<"程序不能完成指定的操作,任务被迫放弃"<<endl;
exit(1);
}
}
for(i=0;i<pointercunt;i++)
for(k=0;k<arrsize;k++)
{
*( *(data+i)+k )=0; //初始化数据块
}
cout<<"^_^ 内存初始化完成,primedat类的对象构造成功"<<endl;
}

Primedat::~Primedat() //释放内存
{
for(int i=0;i<pointercunt;i++)
{
delete []( *(data+i) );
}
delete []data;
}//finished

void Primedat::initdat(void)
{
datID=onedat/arrnumlimit;
arrID=(onedat%arrnumlimit)/40;
bitblockID=(onedat%40)/10;
switch(onedat%10)
{
case 1:bitID=0;
break;
case 3:bitID=1;
break;
case 7:bitID=2;
break;
case 9:bitID=3;
break;
default:
cout<<"函数异常调用:"<<endl
<<"Prmiedat::initdat(void)"<<endl
<<"参数非法,int onedat="<<onedat<<"程序被迫中止"<<endl;
exit(1);//非法调用时退出
}
tmp=*(*(data+datID)+arrID);
} //end of function

void Primedat::marknonprime(void)
{
*( *(data+datID) +arrID) |= andortable[bitblockID*4+bitID];//将一个非素数所在的位置1
}//end of function

void Primedat::showprime(void)
{ unsigned short bitsig[4]={1,3,7,9};
if( (tmp&andortable[bitblockID*4+bitID]) ==0)
{
cout<<onedat<<" ";//输出一个素数
scrwd++;
if(scrwd==8)
{
scrwd=0;
cout<<endl;//达到8个数后换行
}
}
}//end of function

//end of Primedat.cpp
#include<math.h>
#include<stdio.h>
#include<iostream.h>
#include<string.h>
#include"Primedat.cpp"
#include<time.h>
int main(void)
{
string cmd; //用户输入的命令
const int goal=100000000; //计算目标1亿
int basecunt=3; //外层计数器
int baseflag=3; //外层加标志
int numcunt; //内层计数器
int numflag; //内层加标志
clock_t start ,end; //计算开始和终止时间
start=clock(); //开始计时
Primedat *tenb;
tenb =new Primedat(goal);
const int basegoal=(int)sqrt(goal); //只需计算到goal^(1/2)
int multmp; //中间乘结果
while(basecunt<basegoal) //开始
{
numcunt=basecunt;
numflag=baseflag;
while( (multmp=basecunt*numcunt) <goal)
{
tenb->onedat=multmp;
tenb->initdat();
tenb->marknonprime();
numflag++;
if(numflag==4)//1,3,7,9
{
numcunt+=4;
numflag=0;
}
else
{
numcunt+=2;
}
}
baseflag++;
if(baseflag==4)
{
basecunt+=4;
baseflag=0;
}
else
{
basecunt+=2;
}
}

end=clock();
cout<<"time: "<<(double)(end-start)/CLOCKS_PER_SEC<<endl;
//生成数据完毕

cout<<"由于生成数据过多,逐一显示将耗费大量时间,"<<endl
<<"输入\"show\"显示,其它任意字符退出"<<endl;
cin>>cmd;
if(cmd=="show")
{
baseflag=0;
for(basecunt=7;basecunt<goal;)
{
tenb->onedat=basecunt;
tenb-> initdat();
tenb->showprime();
baseflag++;
if(baseflag==4)
{
basecunt+=4;
baseflag=0;
}
else
{
basecunt+=2;
}
}

}
delete tenb;
return 0;
}//end of main
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
***************************************




永不停息[11750919] 2002-09-16 19:50
题目:实现
C,实现(with c++)

暑假回家时我的二姐给了我100大洋充作路费,
由于坐车只需30元,偶把余下的钱买了两本书:
《高质量程序设计指南》和《c++语言程序设计》(清华版,比较便宜)
学了一周,也算明白了一点东西。

我非常喜欢c++的类对数据的隐藏和封装。
让程序看起来简洁明了,而功能强大。


看到多态性的定义:

"不同类的对象对同一消息的不同反应"。

我想起了一些有趣的东西:

在我们这里,人人都知道"狗儿"是用来叫狗用的。
你对着一条狗一叫"狗儿",它就会摇头晃脑的跑上来舔你的手。
你对着一个人一叫"狗儿",他就会拎着拳头上来把你扁晕。
但是,如果你也有可能遇到这样的情形:
你对着一个人一叫"狗儿",他上来了,不是扁你,而是亲热地跟你握手,为什么?

因为:这个人的小名叫"狗儿"

好了,言归正传:

以下的程序在borland c++ complier 5.5下通过,
但在visual c++ 6.0下无法通过,原因是不支持string类的操作
各位可以自己改一改

效果:
PⅢ850
128M ram内存
算到1亿用时:48S
算到10亿用时:580S
算到100亿估计用时:6000S
这仍然太慢,需要改进。

要想算到100亿,unsigned int(max=42亿)
是不行的,需要改进记数格式。


不管程序本身怎么样,这毕竟是我写的第一个c++程序。
让各位见笑了

大家可以用c自己写一个,效果比这个要好。

本来好好的缩进格式,被tencent的傻cgi一过滤,就面目全非了。
大家如果想看好的缩进格式的程序和图表,可以给我留言,把你的邮箱地址给我。
或直接点"回复"->"引用"->"全部"

然后把文字输入框里的文本粘贴到写字板(不是记事本)里,把">"全部替换掉
就可以了
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
我们可以用0来表示它是素数,1来表示它是非素数
那么,我们可以用一个char 类型的数组来表示了:
这样一来,需要的内存:3.78G

已经是windows可以管理的了。

可是,这毕竟不是我们想要的结果。
既然它的属性只有0,1两种标志,
为什么不用位(bit)呢?

这是个好主意。

呵呵,内存的需要量顿时大减。476M,可以了。

但是,不可能一次就申请这么多的内存,也不可能管理这么大的数组
我用以下方法来实现:
:

用一个指针数组来存放一系列的指针
每一个指针指向一个unsigned int 数组。
unsigned int 数组中的每一个数据可以存放16个位(bit)

+----+----+-----+----+-----+----+
|dat0|dat1|dat2 |dat3| ... |datn| <=-- data array 0
+----+----+-----+----+-----+----+
^
|
+----+----+-----+----+
|add0|add1| ... |addn| <=--pointer array
+----+----+-----+----+
|
\ +----+----+-----+----+-----+----+
-=> |dat0|dat1|dat2 |dat3| ... |datn| <=-- data array 1
+----+----+-----+----+-----+----+
用图形来表示:
..□...□.□...□.□...□
...\.|./...\.|./...\.|./
.....★......★.....★
.......\.....|...../
........\....|..../
.........\...|.../
..........\...../
...........\.|./
.............☆

□:一个unsigned int 数据
★:一个unsigned int 数组
☆:一个unsigned int指针的指针数组
. :填充占位符,无意义
| 和 \ 和 /:关系连接符

这样,只要知道一个数据所在的:
指针数组的位置
数据数组中的位置
数据中位(bit)的位置
我们就可以知道这个数的大小。

反过来,亦OK。



我没学过数据结构,但从它的形状来看,这有可能是树。
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
我们可以试一试:


那么如何检测它们的乘积是在这个序列中的呢?
对了,它们乘积的个位数(由个位数的乘积决定),只要是1,3,7,9,
那么,这个乘积一定是在这个序列中:
我们来看所有的组合(幸亏不是太多):
1,3,7,9
x 1
-------------
=1,3,7,9

1,3,7,9
x 3
-------------
= 3,9,1,7

1,3,7,9
x 7
-------------
= 7,1,9,3

1,3,7,9
x 1
-------------
=1,3,7,9
这个性质真是好,省了我们多少工作!

那么,我们是否能保证所有的非素数都被这个序列的乘积给挑出来了呢?


检测完2,4,6,8,0,5的乘积组合后,我可以肯定的告诉你:

是的!

完美的性质!!!!!!!!!!!!!!
我终于明白陈景润为什么研究数论而终生不倦了。


数学上的证明如果哪位有兴趣,可以自己证明一下。



************************

B ,数据结构:



由于我们采用的是只检测非素数的方法,而我们所要的只是素数。
所以,必须有上边的序列存在。

我们用一个int 数组?

显然不可能,100亿内这个序列有40亿个整数
按每个整数2个字节计算,需要的内存空间是:
7.46G!
这么大的内存,只有中小型机才可能提供。

我们真的需要那么多的内存么?

再看这个序列,它是有一定规律的:

1 @ 1 , 3, 7, 9
2 @ 11 , 13, 17, 19
3 @ 21 , 23, 27, 29
... ...
n @ n*10+1, n*10+3, n*10+7, n*10+9

也就是说,这个序列中的数,只要知道它是第几个数
就能知道它的大小

而这个序列中的数的最重要属性就是:
素数||非素数
用户 昵称 2003-04-29
  • 打赏
  • 举报
回复
我们需要更好的算法.

其实,检测一个数是否是素数,只用检测到它的平方根大小就可以了,

所以上边的检测范围可以缩小到goal^(1/2)

可是,这仍然不行,
慢的要命。

再看:
1,2,3,4,5,6,7,8,9,10,11,12,13,......

我们能不能把不用检测的数滤去,然后,就可以提高速度了。


看自然数的规律:

以2,4,6,8,0结尾的数,可以被2整除。
以5,0结尾的数,可以被5整除。
所以,只用检测1,3,7,9结尾的就可以了。


跟上边的结合起来,

程序的确省了不少时间,但,这仍不够。


***************************
*..................................................*
*...............只跟素数有关.......................*
*..................................................*
***************************

我们来看一个素数分解的问题:

n1
/ \
n2 p1
...\
pn
上图的意思是,把一个非素数,分解为一系列的因子
如果分解得的因子不是素数的话,继续。

用数学的语言来说就是:
一个非素数,一定可以被一个素数整除。

而根据素数的定义,一个素数,一定不可以被一个素数整除。

呵呵,检测的时候,只用用素数来检测就可以了。

又省了不少时间。

***************************
*..................................................*
*...............倒行逆施...........................*
*..................................................*
***************************

仔细看上边的算法,一个数都要检测多次,才能确定是素数,
那么,能否,只检测一次?


对一个单独的数来说,这显然是不可能的。

这个念头先放下。


既然正着想这么难办,为什么不倒过来呢?
对于两个数的乘积,一定是非素数
这是肯定的了
这样一个数只检测一次,就能确定是非素数。


那么,对于以下序列:

1 @ 1 , 3, 7, 9
2 @ 11 , 13, 17, 19
3 @ 21 , 23, 27, 29
... ...
n @ n*10+1, n*10+3, n*10+7, n*10+9,

只用剔除非素数,就是素数了。


关键是,用什么样的数来检测,才能保证把这里边的所有非素数都去掉呢?

用这个序列:
1 @ 1 , 3, 7, 9
2 @ 11 , 13, 17, 19
3 @ 21 , 23, 27, 29
... ...
n @ n*10+1, n*10+3, n*10+7, n*10+9,
本身怎么样?
加载更多回复(1)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧