朴素的原始性测试优化

时间:2012-02-10 04:29:01

标签: java c++ performance optimization

我有一个算法来测试素数,它使用了这里列出的天真实现http://en.wikipedia.org/wiki/Primality_test#Naive_methods

       static boolean check(int n)
   {
           if(n == 2 || n == 3)
           {
                   return true;
           }
           if(n < 2 || n % 2 == 0 || n % 3 == 0)
           {
                   return false;
           }
           for(int i = 6; i * i <= n; i += 6)
           {
                   if(n % (i - 1) == 0 || n % (i + 1) == 0)
                   {
                           return false;
                   }
           }
           return true;
   }

我一直到6k + 1部分,但在那之后,我迷路了。我还能如何进一步优化速度?

1 个答案:

答案 0 :(得分:2)

如果您想坚持使用朴素方法,那么下一步就是使用您链接到的维基百科页面中列出的下一个属性:

  

因此,对于i = 1,7,11,13,17,所有素数都是30k + i的形式,   19,23,29(即对于i <30使得gcd(i,30)= 1)。

除了你可能选择略微不同/更多的素数而不是2.3.5

你会用一个30步进循环替换6步进循环,(并用手检查所有小于30的质数)

代码可能如下所示:

    static boolean check(int n)
   {
           if(n<30)
           {
              return n==2 || n==3 || n==5 || n==7 || ...
           }

           for(int i = 30; i * i <= n; i += 30)
           {
              if (n % (i + 1))==0 return false;
              if (n % (i + 7))==0 return false;
              if (n % (i + 11))==0 return false;
              if (n % (i + 13))==0 return false;
              if (n % (i + 17))==0 return false;
              if (n % (i + 19))==0 return false;
              if (n % (i + 23))==0 return false;
              if (n % (i + 29))==0 return false;
           }
           return true;
   }

但是你会注意到这会扫描8/30(= 27%)个数字,而6个步进循环扫描2/6 (= 33%)所以它扫描的数字减少了约20%,所以你期望最多加速20%。当您向列表中添加更多素数时,您将获得递减收益。

真的,如果你需要快速素数检查,那么你需要摆脱天真的方法。之前有很多关于堆栈溢出问题的问题。