Java程序需要花费很长时间才能运行大量数据
我正在编写一个Java程序来计算一个大数中的最大素数因子。但是我对程序的复杂性有一个问题,我不知道是什么导致程序永远运行在大的数字上,它在小的数字上运行良好 我的工作如下:Java程序需要花费很长时间才能运行大量数据,java,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) {
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);
}
}
for (i = 2; i < number; i++)
{
if (!isPrime(i))
{
factorArray.remove(i);
System.out.println(factorArray);
}
}
System.out.println(Collections.max(factorArray));
}
因此,代码的下一部分如下所示:
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);
}
}
for (i = 2; i < number; i++)
{
if (!isPrime(i))
{
factorArray.remove(i);
System.out.println(factorArray);
}
}
System.out.println(Collections.max(factorArray));
}
(i=2;i
{
如果(!iPrime(i))
{
去除(i);
System.out.println(FactoryArray);
}
}
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;
}
}
public静态布尔值isPrime(长n)
{
如果(n>2&(n&1)==0)
返回false;
对于(int i=3;i*i)
这是一个巨大的数字,你要循环两次。试着每10000或100000次计数(如果我打印了%10000(i)),你就会知道它的速度有多快。你循环了600851475143个数字
long number = 600851475143L ;
for (i = 2; i < number; i++)
long number=600851475143L;
对于(i=2;i
即使我们假设每次迭代只需要很短的时间(只有1微秒),但在循环完成之前仍需要几天的时间
为了使该程序运行得更快,您需要优化主要查找逻辑
将迭代次数减少到合理数目的一种方法是循环直到该数目的平方根
for (i = 2; i < Math.sqrt(number); i++)
for(i=2;i
或
for(i=2;i*i
计算600851475143L的基本因子应不到一毫秒(使用的算法并非完全无效)。您的代码目前缺少的主要部分包括:
边框应该是sqrt(数字),而不是数字。
应在while循环中检查当前值(为了防止非素数因子添加到列表中,减少要检查的范围)。
找到系数后,应将最大值(以及边框)减小到数字/系数
进一步的改进是可能的,例如只迭代非偶数(或只迭代不是2和3的倍数的数)等
codereview()上相同问题的示例实现:
public静态长参数(
最终长输入){
////
如果(输入<2)
抛出新的IllegalArgumentException();
长n=输入;
longlast=0;
对于(;(n&1)==0;n>>=1)
last=2;
对于(;n%3==0;n/=3)
last=3;
对于(long v=5,add=2,border=(long)Math.sqrt(n);v一个可能的解决方案是只测试小于大数的素数是否除以它。
所以我查了一下
for (i=2; i < number; i++)
{
if(isPrime(i))
{
if( number % i == 0)
{
factorArray.add(i);
}
}
}
(i=2;i
{
如果(i)
{
如果(编号%i==0)
{
添加(i);
}
}
}
所以这里我只除以素数,而不是除以所有小于600851475143的数。
但这仍然不是很快,需要对算法进行完全修改以获得最佳算法。@Balkrishna Rawool建议是正确的方法。为此,我建议更改迭代如下:For(I=3;I可能更多的是内存问题,因为您似乎将整数放入了一个列表中。您是否检查了内存的演变情况?以及GC活动?嗯,600851475143是一个非常大的数字。如果您的“较小的数字”是600851475(这本身已经是一个非常大的数字),那么对于这个较大的数字,需要花费至少1000倍的时间。您期望的是什么?您的算法必须是O(N)或更糟糕的O(N^2)您可以做的一个改进是使用HashSet
而不是ArrayList
。但是,即使每个循环迭代只需要纳秒级,程序也需要很多小时。祝贺您!您刚刚发现了现代密码学一个分支的基础。素数分解是一个已知的难题,而t fact用于在多个加密系统中创建公钥/私钥对。如果你要解决这个问题,你将一举摧毁密码理论的一大部分,并可能解决现代计算的圣杯,即P=NP问题。也就是说,这不会发生。我试过使用factoraray.size()相反,但非素数并没有从列表中删除。@Ouissalbenamer,我想你误解了我的意思。这不是你在循环中所做的,你试图访问万亿个数字,这将需要很长时间。没有办法“修复”除非你改进寻找素数的算法。
for (i = 2; i*i < number; i++)
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;
}
for (i=2; i < number; i++)
{
if(isPrime(i))
{
if( number % i == 0)
{
factorArray.add(i);
}
}
}