Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Project Euler#3-解决方案永远运行_Java_Algorithm_Primes - Fatal编程技术网

Java Project Euler#3-解决方案永远运行

Java Project Euler#3-解决方案永远运行,java,algorithm,primes,Java,Algorithm,Primes,我第一次遇到这个问题。感觉它永远不会结束 我的做法: import java.util.TreeSet; public class Euler3 { public static void main(String[] args) { long result = 0; long startTime = System.nanoTime(); long numberGiven = 600851475143L; TreeSet&l

我第一次遇到这个问题。感觉它永远不会结束

我的做法:

import java.util.TreeSet;

public class Euler3 {
    public static void main(String[] args) {
        long result = 0;
        long startTime = System.nanoTime();

        long numberGiven = 600851475143L;
        TreeSet<Long> nums = new TreeSet<>();

        for (long i = 2L; i < numberGiven; i++) {
            if (numberGiven % i == 0 && isPrime(i)) {
                nums.add(i);
            }
        }

        result = nums.last();   

        System.out.print("Result: " + result +
            ".\nTime used for calculation in nanoseconds: " +
            (System.nanoTime() - startTime) + ".");
    }

    public static boolean isPrime(long n) {
        if (n <= 3) {
            return n == 1 ? false : true;
        } else if (n % 2 == 0 || n % 3 == 0) {
            return false;
        } else {
            for (int i = 5; i * i <= n; i += 6) {
                if (n % i == 0 || n % (i + 2) == 0) {
                    return false;
                }
            }
        return true;
        }
    }
}
import java.util.TreeSet;
公共类Euler3{
公共静态void main(字符串[]args){
长结果=0;
long startTime=System.nanoTime();
长数rGiven=600851475143L;
TreeSet nums=新的TreeSet();
用于(长i=2L;in*m
运算

您可以改为使用以下数学“技巧”,我认为这与UNIX
factor
程序使用的相同

由于1上的每个数字要么是素数,要么是一组素数的唯一乘积(集合中可能存在重复项),我们可以开始将该数字除以前两个素数(实际上在过程中减少该数字),直到不再可能(即,它变为奇数)。此时,减少的数字将不会有两个或两的任何倍数作为因子

然后我们继续除以3,直到不再可能

现在你会认为这可能很繁重,但是,因为你已经去掉了所有的“二”因子,所以这个数不可能是四的倍数(或者任何其他偶数)。所以我们检测到它,然后向上移动到下一个五的除数,开始除以它

所以除法运算只针对素数除数,大大加快了运算速度。此外,一旦除数超过(减少的)数的平方根,就不可能有更多的因子,所以我们退出。在这种情况下,减少的数给出了最终的(因此最高的)素数因子

例如,考虑数字<代码> 924 /代码>:

Number  Divisor  Result
------  -------  ------
   924        2*    462
   462        2*    231
   231        2     not divisible, go to 3
   231        3*     77
    77        3     not divisible, go to 4
    77        4     not divisible, go to 5
    77        5     not divisible, go to 6
    77        6     not divisible, go to 7
    77        7*    11
    11*       7     stop since 7 * 7 > 11
因此
924
的主要因素是
{2,2,3,7,11}


现在,我敦促您在查看下面的内容之前自己尝试该算法,因为Euler的全部目的是测试您自己的能力。我只是提供完整性的解决方案:

public class Test
{
    public static void main(String[] args) {
        long startTime = System.nanoTime();

        long number = 600851475143L;

        // Start with a divisor of two,
        // continue until over sqrt(number).

        long divisor = 2L;
        while (divisor * divisor <= number) {
            if ((number % divisor) == 0) {
                // If factor, output then reduce number.

                System.out.println(divisor);
                number = number / divisor;
            } else {
                // Otherwise, move to next divisor.

                divisor++;
            }
        }

        // Final number is final divisor.

        System.out.println(number);

        System.out.print("Time used for calculation in nanoseconds: " +
                (System.nanoTime() - startTime) + ".");
    }
}
对于每一个你检查的是一个因子的数字,你都在做一个内部循环来判断它是否是素数。这意味着你的算法有效地执行了
n*m
运算

您可以改为使用以下数学“技巧”,我认为这与UNIX
factor
程序使用的相同

由于1上的每个数字要么是素数,要么是一组素数的唯一乘积(集合中可能存在重复项),我们可以开始将该数字除以前两个素数(实际上在过程中减少该数字),直到不再可能(即,它变为奇数)。此时,减少的数字将不会有两个或两的任何倍数作为因子

然后我们继续除以3,直到不再可能

现在你会认为这可能很繁重,但是,因为你已经去掉了所有的“二”因子,所以这个数不可能是四的倍数(或者任何其他偶数)。所以我们检测到它,然后向上移动到下一个五的除数,开始除以它

所以除法运算只针对素数除数,大大加快了运算速度。此外,一旦除数超过(减少的)数的平方根,就不可能有更多的因子,所以我们退出。在这种情况下,减少的数给出了最终的(因此最高的)素数因子

例如,考虑数字<代码> 924 /代码>:

Number  Divisor  Result
------  -------  ------
   924        2*    462
   462        2*    231
   231        2     not divisible, go to 3
   231        3*     77
    77        3     not divisible, go to 4
    77        4     not divisible, go to 5
    77        5     not divisible, go to 6
    77        6     not divisible, go to 7
    77        7*    11
    11*       7     stop since 7 * 7 > 11
因此
924
的主要因素是
{2,2,3,7,11}


现在,我敦促您在查看下面的内容之前自己尝试该算法,因为Euler的全部目的是测试您自己的能力。我只是提供完整性的解决方案:

public class Test
{
    public static void main(String[] args) {
        long startTime = System.nanoTime();

        long number = 600851475143L;

        // Start with a divisor of two,
        // continue until over sqrt(number).

        long divisor = 2L;
        while (divisor * divisor <= number) {
            if ((number % divisor) == 0) {
                // If factor, output then reduce number.

                System.out.println(divisor);
                number = number / divisor;
            } else {
                // Otherwise, move to next divisor.

                divisor++;
            }
        }

        // Final number is final divisor.

        System.out.println(number);

        System.out.print("Time used for calculation in nanoseconds: " +
                (System.nanoTime() - startTime) + ".");
    }
}

程序可以像这样简单,在一秒钟内运行:

long val = 600851475143L;
long ans = 0;
for(long i = 2; i*i <= val; i++){
    if(val % i == 0){
       ans = i;
       while(val % i == 0)//This step will make sure that i is prime
           val /= i;
    }
}
if(val != 1){//If val is not 1, so val is a prime
   ans = val > ans ? val : ans;
}
System.out.println(ans);
long val=600851475143L;
长ans=0;
对于(长i=2;i*i ans?val:ans;
}
系统输出打印LN(ans);
答案是6857,这是正确的答案:)


请注意,我们只检查所有
i
值,这些值
i*i
小于
val

程序可以像这样简单,在一秒钟内运行:

long val = 600851475143L;
long ans = 0;
for(long i = 2; i*i <= val; i++){
    if(val % i == 0){
       ans = i;
       while(val % i == 0)//This step will make sure that i is prime
           val /= i;
    }
}
if(val != 1){//If val is not 1, so val is a prime
   ans = val > ans ? val : ans;
}
System.out.println(ans);
long val=600851475143L;
长ans=0;
对于(长i=2;i*i ans?val:ans;
}
系统输出打印LN(ans);
答案是6857,这是正确的答案:)


请注意,我们只检查所有
i
值,这些值
i*i
小于
val

使用BigInteger而不是long?
int i
在iPrime中应该是
long i
,但我怀疑你的程序仍然需要一段时间才能修复(而不是永远)。我希望你没有编辑,我实际上笑了@“几年。”所以,用词来说,“明显的改变”"就是将发现的每个因子按升序进行划分,这使得所有的素性检查都变得不必要。并不是在
i
时枚举潜在因子,而是
i*我使用大整数而不是长整数?
inti
在iPrime中应该是
long i
,但我怀疑你的程序仍然需要一段时间我希望你没有编辑,我实际上笑了“几年”。所以,用词来说,“明显的改变”就是将发现的每个因子按升序进行划分,这使得所有的素性检查都是不必要的。并不是在
i
时枚举潜在因子,而是在
i*i时只枚举每个numb