Java程序永远运行大量

时间:2016-10-04 19:16:38

标签: java

我正在编写一个Java程序来计算大数的最大素数因子。但是我对程序的复杂性有一个问题,我不知道是什么导致程序永远运行大数字,它适用于小数字。

我进行了如下操作:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class Largest_prime_factor {

public static void main(String[] args) 
{
    //ArrayList primesArray = new ArrayList();
    ArrayList factorArray = new ArrayList();
    long largest = 1;
    long number = 600851475143L ;
    long i, j, k;

    //the array list factorArray will have all factors of number
    for (i = 2; i < number; i++)
    {
        if( number % i == 0)
        {
            factorArray.add(i);

        }
    }

此处,数组列表将包含该数字的所有因子。 所以我只需要获得主要的,为此,我使用了一种检查数字是否为素数的方法,如果它不是素数,我使用以下方法将其从列表中删除:

 java.util.ArrayList.remove() 

所以代码的下一部分如下:

for (i = 2; i < number; i++)
        {
         if (!isPrime(i))
         {
             factorArray.remove(i);
             System.out.println(factorArray);
         }
        }


        System.out.println(Collections.max(factorArray));
    }

最后一行打印出最大数量的factorArray,这正是我要找的。

    public static boolean isPrime(long n) 
    {
        if(n > 2 && (n & 1) == 0)
           return false;
        for(int i = 3; i * i <= n; i += 2)
            if (n % i == 0) 
                return false;
        return true;
    }   

}

上面的函数是我用来确定数字是否为素数之前从列表中删除它。

这个程序适用于小数字,但是为大数字提供输出需要永远,尽管最后一个函数非常快。 起初,我曾经在第一个循环中检查一个数字是否为素数,但它甚至更慢。

5 个答案:

答案 0 :(得分:3)

您正在循环超过600851475143个数字。

long number = 600851475143L ;
for (i = 2; i < number; i++)

即使我们假设每次迭代花费非常短的时间(小到1微秒),它仍然需要几天才能完成循环。

您需要优化您的寻找逻辑,以便该程序运行得更快。

将迭代次数减少到合理数的一种方法是循环直到数字的平方根。

for (i = 2; i < Math.sqrt(number); i++)

for (i = 2; i*i < number; i++)

答案 1 :(得分:2)

600851475143L的素因子的计算应该不到一毫秒(算法效率不是很低)。您的代码目前缺少的主要部分:

边框应为sqrt(数字)而不是数字 应该在while循环中检查当前值(以防止将非素因子添加到列表中,减少范围以进行检查)。
最大在找到因子后,应将数值(以及边界)减少到数字/因子。

可以进一步改进,例如仅迭代非偶数(或仅迭代不是2和3的倍数的数字)等。

关于codereview(link)的相同问题的示例实现:

public static long largestPrimeFactor(
        final long input) {
    ////
    if (input < 2)
        throw new IllegalArgumentException();

    long n = input;
    long last = 0;
    for (; (n & 1) == 0; n >>= 1)
        last = 2;
    for (; n % 3 == 0; n /= 3)
        last = 3;
    for (long v = 5, add = 2, border = (long) Math.sqrt(n); v <= border; v += add, add ^= 6)
        while (n % v == 0)
            border = (long) Math.sqrt(n /= last = v);
    return n == 1 ? last : n;
}

答案 2 :(得分:1)

 for (i = 2; i < number; i++)
    {
        if( number % i == 0)
        {
            factorArray.add(i);

        }
    }

对于较大的输入尺寸,您将访问该数字的值。删除因子的循环也是如此。

   long number = 600851475143L ;

这是一个巨大的数字,你需要两次循环。尝试计算每10,000或100,000(如果i%10000打印(i))并且您将了解它的移动速度。

答案 3 :(得分:1)

其中一种可能的解决方案是仅测试小于大数的素数是否除以它。 所以我检查了

        for (i=2; i < number; i++)
        {
            if(isPrime(i))
            {
                 if( number % i == 0)
                 {
                     factorArray.add(i);                    
                 }
            }   
        }

所以在这里我只会用素数除以而不是除以所有小于600851475143的数字。 但这仍然不是很快,需要对算法进行彻底修改才能获得最佳算法。

答案 4 :(得分:0)

@Balkrishna Rawool建议是正确的方法。为此,我建议改变迭代,如下所示:for(i = 3; i&lt; Math.sqrt(number); i + = 2)并手动处理2。这将减少你的循环,因为除了2之外的偶数都不是素数。