素数计算器不使用大数字

时间:2015-06-09 19:39:17

标签: java prime-factoring

我正在尝试打印出一个数字的所有主要因素。我的代码如下:

public static boolean isPrime(long n){

    long i = n;

    while (i > 0){

        if (n % i == 0 && !(i == 1 || i == n)){

            return false;

        }
        i--;
    }

    return true;

}


public static void primeFactors(long n){

    long i = n;
    while (i > 0){

        if (isPrime(i)){
            System.out.println(i);
        }
        i--;
    }

}

此代码适用于小数字:5,5000,例如。当我向方法输入600851475143时,我的程序运行并且没有输出任何内容。为什么会这样?

7 个答案:

答案 0 :(得分:5)

你的素性测试功能太可怕了。

  1. 快速获胜:向前计数而不是倒退。目前,您只需计算一半数量,直至找到一个因素!这可能是你观察到的延迟的原因。

  2. 更好一点:将奇数计算到平方根。

  3. 或许更好:将素数计算到平方根。根据要求预先计算使用筛子的那些。

答案 1 :(得分:1)

其他答案都集中在你的函数isPrime上,效率很低。我将专注于您的函数primeFactors,这是不正确的。实际上,你可以看到它以相反的顺序打印最多n个素数,而不是n的素因子。相反,做

public static void primeFactors(long n) {
  // Handle factors of 2
  while (n%2==0) {
    System.out.println(2);
    n /= 2;
  }

  // Handle all odd prime factors except the largest
  for (long p = 3; p*p <= n; p += 2) {
    while (n%p == 0) {
      System.out.println(p);
      n /= p;
    }
  }

  // Handle the largest prime factor
  if (n > 1) {
    System.out.println(2);
  }
}

您可能会注意到isPrime从未使用过!事实上它并不需要:只要它们在您找到它们时被删除,您打印的所有数字都将是素数。

这里有许多可能的改进,但这种方法足够快。一种简单的方法是计算Math.sqrt(n)的上限并将p与其进行比较,而不是每次都将p相乘。您可能还想检查0和负数,可能还需要1,这取决于您希望如何处理这些数字。

答案 2 :(得分:0)

当输入数字为600851475143时,您的程序没有打印任何内容,因为检查素数的方式很慢。如果有足够的耐心,你的程序会打印一些东西 - 但这可能是几小时,几天甚至几年。您需要为此计算提出更好的算法。

答案 3 :(得分:0)

简短回答:该程序实际上并未终止。您正在使用的方法是检查素数的最低效方法之一。查看Sieve of Eratosthenes以获得易于理解,相当高效的算法。

答案 4 :(得分:0)

无需检查n个数字以检查n是否为素数或从0开始,从0开始到n / 2:

public static boolean isPrime(long n){

        long i = 2;

        while (i < n/2){

            if (n % i == 0 ){

                return false;

            }
            i++;
        }

        return true;

    }

这会使效果加倍

答案 5 :(得分:0)

虽然数字不在长原始值范围之外(9,223,372,036,854,775,807),但您应该使用BigInteger,因为BigInteger具有此功能,我认为它比包括您的其他实现更有效。

new BigInteger(yourNumer).isProbablePrime(100) // returns true or false

此外,通过使用许多数学方法和算法来进行素性测试,有一些方法可以更快地运行数字&lt; 64位,有一些更好的测试更大的数字。还有其他一些方法here

答案 6 :(得分:0)

将您的方法更改为以下内容:

public static boolean isPrime(long num) {
    for (int i = 2; i < Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

应该足够有效。