您的位置:首页 > 其它

筛选法找素数算法的一点改进

2016-09-04 20:33 274 查看
自从接触编程以来,发现,选找素数这一题目一直是算法界一个长盛不衰的题目,而筛选法似乎是这一题目巧妙极致的一个解法。不过不知足的我们依然不肯罢休,对程序中那几次重复运算始终耿耿于怀。什么时候电脑才能像我们一样不知是机械的重复呢?
呵呵,我们还是先看一下这个问题中的重复运算吧!
2*20=40,5*8=40,那么,对于40这一个合数,程序中两次对他进行了筛选,越大的合数,在其上浪费的运算量越大,在程序中如果能检测到这一点从而有选择的跳过的话将节省好多次运算。今天我们就针对这个问题来讨论一下。
先看一下2*20=40这个运算吧,2是第一个参加运算的数,此时,所有的数还都是素数的标志,因此它必须参加运算,因为一个合数至少要具备的条件是:必须是两个以上比他小的素数的乘积。而在进行5*8这次运算时,8已经是合数了(2*4时已经筛选掉了),而且它的结果与前面的造成了重复,最终的原因是不是因为它是合数的原因呢?我们是不是应该加一项判断,在运算时忽略掉所有被打上合数标志的呢?
我们再来看一下2,8这两个数吧,2*2必须进行,4被筛选掉了,然后是2*3,筛选掉6,然后呢,2*4么,别忘了,4已经被筛选掉了,它将没有资格参加这次运算,那么8这个合数就永远没有机会筛选掉了(比他小的素数只有2),因此这种方法下降导致N*M^X(X〉=2)被忽略掉。我们再来看一下40这个数,这里的2、5、8这三个数的关系是,8是在进行2这个周期的运算上被筛选掉的,如果我们把前面周期运算筛选掉的和数忽略是不是就可以没有妨碍了呢?
纵观所有的合数,每个合数都可以分解质因数,最后分解为只含有几个素数的积。假设一个和数m被分解为a*a*b*b*c*c,a<b<c,在进行a这一周期运算时,a*a被筛选掉,但不忽略,所以a*a*b,a*a*b,a*a*b*b,a*a*b*b*c,a*a*b*c,a*a*b*c*c和a*a*b*b*c*c都将被筛选掉,无一漏网。而在进行b这一周期运算时,由于a*a*b*c*c在上次已经被筛选掉了,不再参加运算,因此,a*a*b*b*c*c不会被运算两次的。同理a*a*b,a*a*b*b,a*a*b*b*c,a*a*b*c,a*a*b*c*c也都不会在参加运算。
方法的可行性已经通过验证了,那么怎样识别那个合数是以前运算的结果那个是这次运算的结果呢?既然我们能用0和1来表示素数和合数,为什么不能用其他的数来表示呢!
以搜索1000以内所有素数为例,用1000来表示素数,其他的来表示合数,当然如果搜索10000以内的素数,建议将10000作为素数标志,用n表示在进行n这个周期时筛选掉的数。该算法的Perl程序如下


@a=(1000,1000);

for (i=2;i<=1000;i++)$a[$i]=1000;s=sqrt(1000);

for (i=2;i<=s;i++)

{

ss=1000/i;

for (j=i;j<=ss;j++)
{
next if (a[$j]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: