一道笔试题 题目是这样的:判断一个小于1000的正整数是否为素数。

题目是这样的:判断一个小于1000的正整数是否为素数。

素数的定义就不说了,以下直接分析解法,毕竟是在写与专业相关的东西,是给本专业的人看得,所以看的人应该有点基础吧?!求素数的问题是一个数学上的难题,这是常识,但是本题目限制了最大范围是在1000以内,所以就可以尝试找出一个足够好的解了。首先给出一个最普通的解,就是取需要判断的数的平方根为上限,然后从2开始循环除以这个需要判断的数,如果可以被整除那么就不是素数,否则就是素数。这个解法非常的普通,如果是直接写程序,应该还说得过去,但是作为选拔人才竞争职位的笔试题这样的解法是说不过去的。应该充分利用题目中的限制条件给出一个更好的解。
首先考虑的是虑除偶数,这样需要处理的数就少了一半。一开始先判断这个数是否为偶数,如果是那么就是非素数,否则再开始循环按个除。但是这个时候除数不需要偶数了,于是循环的次数可以减半,这是一个能很明显提高效率的办法。然后接着考虑,利用判断偶数去掉了一半,那么能不能利用是否为3整除,再去掉三分之一呢?这个当然是可以的。如此不断的想下去,就可以设法去掉四分之一,五分之一...。但是,显然越往下作效率提高的程度就越不明显了。因为对于被三整除的数来说由于有些数字是可以同时被2整除的,所以实际上减少的循环次数没有达到三分之一。基于同样的理由后面减少的次数会比期望的更少。而且还有一个问题是考虑越多循环递增的控制越不好做。我想到这里认为,好像减半已经是可以达到的足够好的解了。那么事实真的如此么?赫赫,当然不是,否则就不写这篇日志了。通过进一步的考虑我发现还有一个效率更惊人的做法。
我是这么想的,如果一个数不能被2整除那么以后任何2的倍数都不能整除这个数(这个非常容易理解,不懂得就请不要看这篇日志了);不能被3整除那么以后任何3的倍数都不能整除这个数;...。照这个思路想下去,如果一旦这个数能被整除,那么这个除数是一个什么样的数字呢?这个除数显然不能被2,3,4...等等所有比它小的数字整除,这个结果也很显然。好,那么这个事实恰好是素数的定义。也就是说我们只需要用素数来作除数就可以了。下面的问题是这个结论正确么,有没有办法来验证呢?写个程序穷举?显然很愚蠢,这样做的话就一点味道也没有了,简直是在侮辱这道题目。正确的做法是寻求证明,我们应该用证明的办法来保证这个算法是正确的。这个证明其实不难,因为任何一整数都可以被写成2(当为偶数时需要),和其它素数的幂指数连乘的形式(这是中学里的知识,不明白的自己去补课),如果这些因子中的任何一个都不能整除该数时,那么这个数就是素数。赫赫,这个证明简洁吧!好了,算法的正确性得到证明了,接着就可以干了。由于题目限制输入的数小于1000,所以我们需要找出的所有可以当除数的序列是:2,3,5,7,11,13,17,19,23,29,31。那么大于31的素数需要考虑么?当然不用,因为大于31的最小素数已经大于1000的平方根了,我们是不需要除的。
下面是源代码,当然还有改进的余地,但是效果已经不明显了,所以放弃了。顺便说一句这些代码我没有测试过阿,有错不管:

// 返回1是素数,否则不是

int IsPrimeNumber(int nNumber)
{
     int nDivide[] = {3,5,7,11,13,17,19,23,29,31};
 
     // 如果这个数不在要求的范围内,或者是一个偶数,那么就不是素数
 
     if (nNumber <= 0 || nNumber >= 1000 || nNumber mod 2 == 0)
          return 0;
 
     for (int i = 0; i < 10; i++)
     {
          if (nNumber == nDivide[i])             // 如果恰好等于素数,那么这个数就是素数了
                return 1;
          if (nNumber mod nDivide[i] == 0)    // 如果被整除就不是素数
                return 0;
     }
 
     

     return 1;                                         // 没有被整除那么就是素数
}


就是这样的代码,居然还说我写的不足够好,而得不到职位,那帮人的素质我就不说了。

 

 

思维慎密

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值