Prime测试仪的速度

时间:2013-03-25 23:30:22

标签: java testing performance processing-efficiency

我在Java中接受了一项家庭作业,创建了可以找到Prime数字等的类(你会在代码中更好地看到)。

我的代码:

    class Primes {

    public static boolean IsPrime(long num) {
        if (num%2==0){
            return false;
        }

        for (int i=3; i*i<=num;i+=2) {
            if (num%i==0) {
                return false;    
            }
        }
        return true;
    }   //  End boolen IsPrime

    public static int[] primes(int min, int max){
        int counter=0;
        int arcount=0;

        for (int i=min;i<max;i++){
            if (IsPrime(i)){
                counter++;
            }   
        }

        int [] arr= new int[counter];
        for (int i=min;i<max;i++){
            if (IsPrime(i)){
                arr[arcount]=i;
                arcount++;
            }               
        }
        return arr;
    }   //  End Primes

    public static String tostring (int [] arr){
        String ans="";
        for (int i=0; i<arr.length;i++){
            ans= ans+arr[i]+ " ";
        }
        return ans;
    }

    public static int closestPrime(long num){
        long e = 0 , d = 0 , f = num;
        for (int i = 2; i <= num + 1 ; i++){
            if ((num + 1) % i == 0){
                if ((num + 1) % i == 0 && (num + 1) == i){
                    d = num + 1;
                    break;
                }
                num++;
                i = 1;
            }
        }
        num = f;
        for (int i = 2; i < num; i++){
            if ((num - 1) % i == 0){
                if ((num - 1) % i == 0 && (num - 1) == i){
                    e = num - 1;
                    break;
                }
                num--;
                i = 1;
            }
        }
        num = f;
        if (d - num < num - e) System.out.println("Closest Prime: "+d);
        else System.out.println("Closest Prime: "+e);

        return (int) num;
    }   //  End closestPrime

}//end class

我的代码的目标是更快(和更正确)。我在实现这个目标时遇到了困难。建议?

**新代码:

class Primes {

     public static boolean IsPrime(int num) {

         if (num==1){
             return false;
         }
         for (int i=2; i<Math.sqrt(num);i++) {
             if (num%i==0) {
                 return false;
             }
         }
         return true;
     }
          //  End boolen IsPrime

     public static int[] primes(int min, int max){
         int size=0;
         int [] arrtemp= new int[max-min];

         for (int i=min;i<max;i++){
             if (IsPrime(i)){
                 arrtemp[size]=i;
                 size++;
             }   
         }

         int [] arr= new int[size];
         for (int i=0;i<size;i++){
                arr[i]=arrtemp[i];

             } 
         return arr;

     }  

    public static String tostring (int [] arr){
        String ans="";
        for (int i=0; i<arr.length;i++){
            ans= ans+arr[i]+ " ";
        }
        return ans;
    }

    public static int closestPrime(int num) {
        int count=1;    
        for (int i=num;;i++){

            int plus=num+count, minus=num-count;
            if (IsPrime(minus)){

                return minus;

            }

            if (IsPrime(plus)) {
                return plus;

            }
            count=count+1;
        }
    }   //  End closestPrime

}//end class

我确实试着让它好一些。你怎么看,它可以改进得更多? (速度测试仍然很高......)

3 个答案:

答案 0 :(得分:1)

在您的primes功能中:

  • 检查当前号码是否可被2整除
  • 检查是否为素数
  • 创建一个数组以输出您的输出。
  • 在将数据放入数组之前,再次检查该范围内的每个数字是否具有素数。

问题出在最后一步。通过仔细检查每个数字是否为素数,您将复制最昂贵的操作。

您可以使用动态数据结构,并在找到时为其添加素数。这样你只需要检查一次。

或者,您可以创建一个布尔数组,该数组是您输入范围的大小。然后,当您找到素数时,将相应的数组值设置为true。

<强>更新

您仍然可以进行一些改进,但有些工作需要比其他工作更多的工作。查看测试的具体情况,看看哪些适合您的需求。

低调的果实:

  • 使用ArrayList收集素数,因为您在primes中找到素数,而不是将值循环两次。
  • closestPrime中,您正在检查num两侧的每一个值:其中一半是偶数,因此不是素数。您可以调整代码以仅检查奇数的素数。

实施的诡计:

最重要的是,您应该花些时间确定代码中瓶颈的确切位置。通常,性能问题是由我们认为非常好的代码引起的。您可以考虑查看开发环境中可用的代码分析选项。

答案 1 :(得分:0)

你对isPrime()进行了不少调用,每个调用都非常昂贵。你的第一步应该是尽量减少你这样做的次数,因为对于任何给定的数字,结果都不会改变,没有必要多次调用。您可以通过在计算值后存储值来使用memoization执行此操作:

ArrayList<Integer> memoList = new ArrayList<Integer>();
for(int i = 0; i < max; i++) {
  if(isPrime(i)) {
    memoList.add(i);
  }
}

现在memoList包含你需要的所有素数,最多可以max,你可以快速遍历它们,而不需要每次都重新计算它们。

其次,您可以改进isPrime()方法。你的解决方案循环遍历从3到sqrt(n)的每个奇数,但为什么不绕过素数,现在我们知道它们?

public static boolean IsPrime(long num) {
    for(int p : memoList) {
        if(num % p == 0) {
            return false;
        }
    }
    return true;
}

这些更改应该可以显着提高代码的运行速度,但是已经有很多研究甚至更有效的计算素数的方法。 Prime Numbers上的维基百科页面提供了一些关于你可以试验的进一步战术(尤其是优质筛子)的非常好的信息。

请记住,因为这是家庭作业,所以当你打开它时你应该确定引用这个页面。欢迎你使用和扩展这个代码,但不引用这个问题,你使用的任何其他资源都是抄袭。< / p>

答案 2 :(得分:0)

我发现你的答案有几个问题。首先,2是素数。你在IsPrime的第一个条件打破了这一点。其次,在你的素数方法中,你骑自行车从最小到最大的所有数字。您可以放心地忽略所有负数和所有偶数(就像在IsPrime中一样)。将这两种方法结合起来并节省所有额外的周期更有意义。