如何让我的程序更快。(完美的数字查找器)在java?

时间:2013-12-02 09:49:22

标签: java perfect-numbers

我可以更快找到perfect numbers吗?我试图用数组和另一种算法让它更快,但没有一种能让它更快。

public class Perfect{
    static long perfectNumber;
    static long startTime = System.nanoTime();
    static long endTime;
    static long mersenne;

    public static void main(String[] args) {

        long p = 2;
        while (p < 32) {
            if( p % 2 == 0&&p!=2){
                    p++;
            }
            else{
            if (isPrime(p) == true) {

                mersenne = (long) (Math.pow(2, p) - 1);
                if (isPrime(mersenne) == true) {
                    perfectNumber = (long) Math.pow(2, (p - 1)) * mersenne;
                    System.out.println(perfectNumber);
                }
            }
            p++;
        }

    }
        endTime = System.nanoTime();
        System.out.println("Time:   " + (endTime - startTime) + "ns"
                );
    }
    private static boolean isPrime(long testPrime) {


            for (long i = 3; i < Math.sqrt(testPrime); i += 2) {

                if (testPrime % i == 0) {

                    return false;
                }
        }

        return true;
    }
}

1 个答案:

答案 0 :(得分:0)

您可以进行一些小的改进 - 可能没有一个会对运行时间产生任何影响:

  1. 使用p % 2可能导致分割 - p & 1不会,因此应该快一点。
  2. 您可以轻松预先计算所有素数,直至达到合理的限制。
  3. 在所有情况下,
  4. Math.pow(2,x)2 << x等效,可能会更快。
  5. 在循环中打印是浪费 - 您应该将所有结果收集到列表中并在最后打印出来。
  6. 除了那些微不足道的,可能是过早的优化之外 - 你应该运行几百次计算,并在尝试任何优化之前花费平均时间。

    顺便说一句 - 仅仅因为你使用nanotime并不意味着你得到了纳秒分辨率 - 远非它。

    另外 -

    正如维基百科的文章指出的那样 - 你可以通过列举那里提到的常见二进制模式来避免大部分计算:

    for ( int i = 0; i < 10; i++ ) {
      long q = ((1 << (i+2)) - 1) << (i+1);
      // Printing BigIntegers in binary is easy.
      BigInteger bq = BigInteger.valueOf(q);
      System.out.println(q+" = "+bq.toString(2));
    }
    
    6 = 110
    28 = 11100
    120 = 1111000
    496 = 111110000
    2016 = 11111100000
    8128 = 1111111000000
    32640 = 111111110000000
    130816 = 11111111100000000
    523776 = 1111111111000000000
    2096128 = 111111111110000000000
    

    显然你仍然需要测试它们,但你不必测试几乎那么多。

    另外 - 如果你想进一步进入BigInteger,你可以从以下内容开始:

    for ( int i = 0; i < 10; i++ ) {
      BigInteger p = BigInteger.ONE.shiftLeft(i+2).subtract(BigInteger.ONE).shiftLeft(i+1);
      System.out.println(p.toString(10)+" = "+p.toString(2));
      //long q = ((1 << (i+2)) - 1) << (i+1);
      //BigInteger bq = BigInteger.valueOf(q);
      //System.out.println("    "+bq.toString(10)+" = "+bq.toString(2));
    }