关于求解素数(C/C++,perl)

         对于素数字,大家都很熟悉了。凡是学习编程的都写过判断素数的程序。我们从最简单的开始,依次深入。

         首先是教科书中的方法,这种方法的思路比较简单,给定一个数num,从2--(num-1),一直实验,若其中某个数字能被num整除,说明num不是素数,返回false,反之,则这个数是素数。很简单的方法,符合素数的基本定义,代码清单如下:   

         bool prime(int num)
         {

                 if (num < 2)

                      return false;
                 for (int i =  2; i < num; i++)

                           if (num % i == 0)
                                 return false;
                  return true;
          }

          上面的代码是最原始的判断一个数是否为素数的方法,但是效率不是很好,原因就在于那个for循环中。其实,在判断的时候没有必要达到(num-1)到达num/2,甚至sqrt(num)就已经足够了(离散数学),所以就有了改进的版本,代码清单如下:

          bool prime(int num)
          {

                  if (num < 2)

                       return 0;
                  int temp = sqrt (num);
                  for (int i =  2; i <= temp; i++)
                            if (num % i == 0)
                                  return false;
                   return true;
           }

           这个程序的要点在于,一定要取到sqrt(num),也就是说要用“<=”,而不是“<”。好了,教科书上的改进方法到此为止,实际上,对于用这个思路判断素数来说的众多方法,这个已经可以看做是比较好的了。当然,其实还是可以改进的,比如说,对于除了2以外的偶数,都不可能为素数,所以可以先判断是否可以整除2,如果可以,返回false,反之在进行下一步判断。如果是非偶数,那么在for里面的迭代也就没有必要++了,直接+=2也是可以的,当然,要把初始变量i=2改成i=3,于是,程序就成了下面这个样子:

            bool prime(int num)
            {
                    if (num == 2)
                           return true;
                    if ( num % 2 == 0 || num < 2)//其实num%2是省去了对一个数字开方的运算
                           return false;
                     int temp = sqrt (num);
                     for (int i =  3; i <= temp; i+=2)
                                if (num % i == 0)
                                      return false;
                     return true;

              }

             对于程序中的num<2,其实并不是想对负数也进行判断,它对应的特殊情况是num=0,或者num=1的情况。教科书的方法,也就是说,大部分的本科生用这样的方法判断一个数是否为素数,但是对于这个方法来说,还是那句老话,时间效率不是很好,O(n^2),在进行ACM的时候,某些情况下是不能满足要求,于是有了更好的筛法。

              ACM中常用的方法是筛法,因为时间效率差不多O(n)吧。它需要借助一个辅助的数组,数组的下标代表待判断的数字,记录的信息代表这个数是否为素数,这就是常说的空间换时间吧。多说是废话,直接代码:  

              int rem[10000]={1,1};//0和1不是素数,置为1,其余的都置为0

              void prime()
              {
                     int temp = sqrt (10000);
                     for (int i = 2 ; i <= temp ; i++)
                            if ( !rem[ i ]  )
                                   for (int j = i + i ; j <= 10000 ; j += i)
                                              rem[ j ] = 1;
               }

               函数结束后,从1---10000,是素数的位都是0,不是的都是1,用的时候只要看是0还是1,就可以了。程序里的10000是数字可能出现的最大值。ACM的另一种常用的方法就是,把给定范围的素数先全部算出来保存到数组里,就像这个样子prim[10]={2,3,5,7,11},用的时候看里面有没有,当然,计算的过程是省略的,数组内的东西全部是事先已经算好了手工写到数组里面的,毕竟这样子查找更快。

              到这里,可以发现,教科书的方法适用于对某个数字的判断,而ACM常用方法更适合在某个数字区间范围内大量的重复判断。

 

              本来,应该到这里就结束的,但是上午的时候看到一个老外的求解素数的方法,感觉思路很有意思,就一并写进来。

              perl -lne ' (1x$_) =~ ^1?$ | ^(11+?)\1+$ || print "$_ is a prime" ',输出结果如下:

1

2

2 is a prime

3

3 is a prime

4

5

5 is a prime

6

7

7 is a prime....

           核心部分为“ ^1?$ | ^(11+?)\1+$”。用到的正是筛法的思想,看看待判断数字是不是某个数字的倍数(通过判断1的个数)。很巧妙的正则表达式的解决素数的方法。有兴趣的同学可以访问http://www.catonmat.net/blog/perl-regex-that-matches-prime-numbers/看看英文解释,比较好懂。

           希望这篇文章能够对你有所帮助。

             

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值