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

这是我第一次在这么专业的社区发表文章,文章有什么不足之处,还请大家多提意见!!

      自从接触编程以来,发现,选找素数这一题目一直是算法界一个长盛不衰的题目,而筛选法似乎是这一题目巧妙极致的一个解法。不过不知足的我们依然不肯罢休,对程序中那几次重复运算始终耿耿于怀。什么时候电脑才能像我们一样不知是机械的重复呢?
      呵呵,我们还是先看一下这个问题中的重复运算吧!
      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 ] < $i );
      
$a [ $i * $j ] = $i ;
   }
}
for  ( $i = 2 ; $i <= 1000 ; $i ++ )
{
   
print   " $i "   if  ( $a [ $i ] == 1000 );
}

      Perl作为一种脚本语言用来做数据运算实在不是明智之举,不过最近刚学的Perl,算是一种实践吧!再说这段程序也比较容易读懂,看了以后应该很容易写出c语言的程序的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值