我正在尝试打印出一个数字的所有主要因素。我的代码如下:
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时,我的程序运行并且没有输出任何内容。为什么会这样?
答案 0 :(得分:5)
你的素性测试功能太可怕了。
快速获胜:向前计数而不是倒退。目前,您只需计算一半数量,直至找到一个因素!这可能是你观察到的延迟的原因。
更好一点:将奇数计算到平方根。
或许更好:将素数计算到平方根。根据要求预先计算使用筛子的那些。
答案 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;
}
应该足够有效。